Professional Documents
Culture Documents
Back in 2010, Craig Zheng made a deal with Wrox to write a book about Symphony CMS. Unfortunately, the Symphony
book project was cancelled.
Project Cancelled
After nine months and ten chapters, Wrox decided to cancel this book project in June 2011. Symphony Start to
Finish was to be the first comprehensive guide to building websites and web applications with Symphony. It was
meant to cover the next major version of the platform, but after Symphony lost its only full-time developer, progress
on that version was delayed significantly, and in the end Wrox was unable to accommodate the extended timeline.
What Now?
The considerable work put into the manuscript will be incorporated into Symphony's free online documentation.
Thank you for generously donating your book to the community, Craig.
The Symphony book was made available for free on GitHub. Keep in mind that the manuscript is not finished and was a
work-in-progress that refers to Symphony 3.0 (which never was released beyond the beta, which was really an alpha)
and Crane (there were plans, which were scrapped, to rename Symphony to avoid confusion with the Symfony PHP
framework). There is still a lot of valuable information to be gleaned from Craig's work, and now it's up to the community to
rework it to align this content with the latest Symphony release. Feel free to fork, update and send pull requests.
Chapters
Chapter 1. Why You Need Symphony
Chapter 2. Symphony in Action
Chapter 3. Getting Started
Chapter 4. Symphony Anatomy
Chapter 5. Content
Chapter 6. Front-end
Chapter 7. Data Flow
Chapter 8. Templating
Chapter 9. System Management
Chapter 10. Planning Symphony Projects
Chapter 11. Adaptive Techniques
Chapter 8 is a particularly good read for anyone who is just getting started with XSLT.
these finer and finer bits. In fact, many observers see in this trend the webs next signpost. Web 3.0, they say, will be a
semantic web in which ever more meaningful data is infused into the content itself.
And the more granular and meaningful content is, the more portable, too. As the web extends itself beyond websites and
even beyond browsers, content is increasingly likely to be used and consumed outside of the context in which it was
created. Web content today is not just disaggregated, its truly diasporic. On the one hand, were publishing more content
in more placesFacebook activity, Flickr photos, Gowalla or Foursquare check-ins, Last.fm playlists, and innumerable
comments, likes, votes, and so on. On the other hand, were also seeing our content disseminated far beyond our own
reach and the reach of our traditional websites. Our Twitter updates are being pulled into all sorts of applications and
devices, and are even being printed in books and on t-shirts. Our blog posts are being read everywhere from feed
readers to Kindles. Our podcasts are being loaded onto mp3 players, and our videos are streaming directly to television
sets. Wherever you look, you can see that web content is powering much more than websites these days.
what kinds of content youre going to be dealing with, you cant know how people will want to use it and interact with it,
especially since we find new ways to use things all the time.
Another challenge is that CMSs cant always foresee where theyll need to be able to extend their reach. Websites
themselves are now just one vector in an online presence. Our CMSs have to account for the fact that we increasingly
want to post, share, and disseminate our content all over the webon websites that it doesnt necessarily know about, in
formats it may not have heard of, and on devices that might not even exist yet! In short, the web changes fast, and the
tools we use to manage content on the web need to keep pace even when they cant yet see over the next horizon.
or albums? And are they displayed on the front end in a dedicated image gallery area, included in other pages as
slideshows, or somewhere else?
A feature-focused system answers all of these questions for you. It defines how the content is captured, managed, and
displayed. It might even go so far as to provide the markup, stylesheets, and JavaScript for the front end. The priority is on
delivering fully articulated features that require minimal work and decision-making from end users, something that can be
really convenient, but only as long as these features are implemented in a way that closely matches your needs.
Make no Assumptions
The more assumptions you make, the more likely it is that youre going to be wrong. And when it comes to things that are
supposed to be usefullike softwarethe more theyre wrong about how we want to use them or what were trying to
achieve, the less useful they turn out to be. This is especially true on the web, where nearly everything is a moving target
and, lets face it, were already likely enough to be wrong as it is.
For example, not everyone wants to put all their content into articles or blog posts, or into a complex hierarchy of pages.
Not everyone wants to organize or display their content in the same way, or sort it in the same order, or deliver it in the
same format.
And even when users do want something predictable like a blog post or an article, not everyone wants it to be made up of
the same pieces. Sometimes itll be the usual: a title, a body, a date, an author, and so on. Sometimes it wont. Some
people will want to include things like subtitles, epigraphs, or postscripts. Some will want to include a writing prompt they
used, or meta information like what theyre listening to or where the post was written. There will even be people who want
to art-direct each post individually, giving it its own stylesheet and assets.
The point is, we humans are a creative bunch, and theres really no telling what were going to cook up. Symphony
understands this, understands that every assumption it makes would be an anchor weighing you down. So it tries not to
JavaScript, CSV, PDF and more. Again, natively. And unlike most other CMSs, Symphonys template language is a fully
open standard, not some proprietary jumble of made-up tags. Instead of memorizing some specialty language and halfcoding your templates in a procedural programming language like PHP, with Symphony you use a powerful, consistent,
rule-based language that is just as useful outside of Symphony as it is within.
Embracing XML and XSLT means that Symphony already, natively, plugs right into all the dynamic, diasporic content that
is at the heart of the evolving web. You dont need any fancy plugins or parsers or converters. You dont need anyone to
build a feature" for all those feeds and APIs you want to interact with. All you need is Symphony.
Your data is increasingly spread out all over the web. Maybe youre posting status updates on Twitter. Maybe youre
uploading photos to Flickr or Facebook or Picasa. Maybe you use a bookmarking service like Delicious, or take notes
with a tool like Evernote. You use these tools because theyre great at what they do, and because they are embedded in
broader social ecosystems. But its still your data, and because these sites (and basically all others) have feeds or XML
APIs, Symphony can put it back in your hands. You can fetch it dynamically and aggregate it for display, or you can
actually import the data right into your own site. Either way, Symphony can help you begin to reclaim all of the content
youre generating around the web every day.
In corporate or organizational environments, Symphony can also make your life a lot easier by facilitating communication
among other disparate applications. In this sort of environment, its fairly likely that your company or client has alreadyexisting systems for managing their information. Maybe its an intranet. Maybe its a CRM application, or a custom
database. As long as its got a simple web services layer or API, Symphony can talk to it, helping you improve the flow of
data throughout your organization and avoid situations where the same content is fragmented or duplicated across
multiple systems.
I worked on a project, for instance, where most of the content that was going to drive the website was already being
managed in an internal CRM. Rather than having to build a custom front-end to the system, or having to keep duplicate
versions of all that content, we were able to use Symphony to grab data directly out of the CRM. This meant that
employees could go on managing their information just as they had before, and anything that was suitable for display on
the website could get pulled out and templated by Symphony.
And this works both ways. Because Symphony has a granular data model, and because XSLT can output almost
anything, your data will never be trapped. If you decide a few years down the line to use another tool, or to move your
data into some external archive, you can just have Symphony fetch your content and transform it into whatever format you
need. In fact, in Part 4 of this book, well do exactly that, using Symphony to build a simple application API.
one as complex as a multi-tiered review and editorial process, Symphony can be set up to accommodate your exact
needs.
Youre a systems administrator. Maybe you work for a government agency or a university. You have to deploy and
support a lot of websites, but their requirements can vary drastically. For maintenance and documentation purposes, you
want the convenience of using a single CMS. For performance and usability purposes, you want the benefits of custombuilt systems. With Symphony, you get both. You get a CMS where each build is essentially a custom CMS.
Youre a highway bandit. You block roads with large, impassable objects and then descend from the woods to steal from
those who land in your clever trap. You actually dont need Symphony to put you in the drivers seatyou have your own
means of getting there. In fact, youre probably in a drivers seat right now, in a car that you stole from the very nice
person to whom this book once belonged. Shame on you.
[0201.png]
Overview
URL: http://jonasdowney.com
Developer: Jonas Downey
Jonas Downey is a clever dude, and one visit to his website should be enough to convince you of that if youre not
inclined to take my word for it. In addition to being a talented writer and web developer, Jonas does some really amazing
work with data visualization and computation, and he whips up all sorts of fascinating conceptual and artistic
experiments. He also blogs, tweets, takes photos, listens to music, and bookmarks interesting sites. His website, or
Interactive Manufactory, is designed to be a virtual home for all these endeavors, a hub both for his day-to-day life and
for his creative work. Like most websites of its kind, it is meant to be a reflection of its ownerhis work, his interests, his
personality, his tastes. The site sports Jonas own homespun design, built using HTML5 and CSS3. It features a
compelling visual portfolio, a bio page, a contact form, and many of the other things youd expect from a personal
website. It also aggregates the scattered digital impressions Jonas makes on the web each day, from Twitter updates and
Last.fm albums to Flickr photos and Delicious bookmarks.
Points of Interest
With his data spread out across so many third-party services (including his own external blog), Jonas wanted a way to
pull it all together. But he wanted to do more with the data than just display it. He wanted to be able to work with it,
manipulate it. So instead of just having Symphony grab and template the data dynamically (which it could easily do),
Jonas used a Symphony extension to import the XML data he collects from each source right into his own sites content
structure.
This means he can go on using these other services and all the tools they offer, but he also gets to keep his own archives
of tweets and bookmarks, for instance. It also means that, because hes got the content stored locally, hes able to mix
and mash it and put it to interesting uses. The most obvious of these is that he takes the bits and pieces that he gathers
and uses them, along with his own daily notes and reflections, to render some pretty neat visualizations of his activity
over time (Figure 2-2).
Figure 2-2
[0202.png]
Developers Thoughts
Truly, this site would never have happened without Symphony. For several years I had envisioned aggregating my
various personal data into a cohesive site, but the available tools were complex and functionally lackluster.
With Symphony, the XML data loading capability was the feature that sold me on day one. I no longer had to worry about
how to get my content into my content management system, which is really what they're supposed to do, isn't it? Once
sold, I quickly discovered all the other great features of the system; in particular I loved the elegant interface, the complete
control over markup and output, XSLT for templating, and abstracted database queries via Data Sources. As an extra
bonus, any time I got stuck on something, the community was super helpful.
It was definitely hard work learning everything, but it was ultimately a complete joy to build with Symphony. And now I'm
already in the process of using Symphony for an even bigger data visualization site.
Jonas Downey
[0203.png]
Overview
URL: http://clorox2.com/mystain/
Developer: Vine Street Interactive
Im notorious for staining just about every shirt Ive ever worn. Ask my wife. And usually I cant be bothered to think about
how to get those stains outto me theyre just soup-dumpling-flavored badges of honor. But Cloroxs nifty (Symphonypowered) myStain app might very well change that.
Available as both a web app and a set of mobile apps, Cloroxs myStain provides entertaining and timely tips for wouldbe stain fighters, whether theyre at home with their full arsenal of laundering products or out and about with little more
than a bottle of water and a packet of salt. Users can browse through a stain library, vote on stain-fighting solutions and
share them with their hapless friends via email or social media, or take a spin with the apps slot-machine-style stain
scenario generator (which is a nice way to feel like youre winning something even when the crotch of your best-fitting
pants has been smeared with sloppy joe).
Points of Interest
The myStain project leverages Symphony to orchestrate the flow of content to and from four different environmentsan
XHTML website, a Flash-based web app, an iPhone app, and an Android app. Symphonys flexible XSLT templating
layer allows the app to output its content in whatever format each environment requires. It provides XHTML for the
website, generic XML for the Flash app, an Apple Plist for the iPhone app, and JSON for the Android app. This means of
course although users can access the apps content in several contexts on several devices, producers only have to
manage their stain tips in one place. And the data flow goes two ways: Symphony also receives user-submitted votes
from all of the different app environments.
The broader website in which the myStain app content appears is actually not Symphony-powered. Its managed by
Cloroxs own proprietary CMS. But again, because of the openness and flexibility of XSLT, the Symphony-powered
portions are able to elegantly integrate with the companys existing architecture.
Developers Thoughts
The primary criterion for myStain's content management was a system that played well with others. When the project
started, we knew the site would be talking to an iPhone app and a Flash component in addition to serving vanilla XHTML.
Since both of these client apps could easily consume XML, I knew Symphony would be a good fit.
Most of our workload on this project was the development of the mobile apps rather than the data service that would feed
them, so we needed to be able to get content web services running quickly, even before the information architecture (IA)
was completely locked in. Before I coded anything, Symphony's extremely straightforward content- and event-modeling
interface had most of the content service up way ahead of schedule, which is always a nice way to start a big project.
As development progressed, requirement changes came in for both the IA as well as what the mobile app developers
wanted. Symphony's use of XSLT was really important in this situation. Since XSLT is built to handle XML, the iPhone
developer had free reign to code for any Plist structure he wanted. Late in the project, when the client added an Android
version to the plan, we chose JSON as the transport format for the Android app. Since XSLT is an open standard, any
generic XSLT solution can be used in Symphony. I easily found a template online that helped me output the necessary
JSON.
To integrate Symphonys output with the Clorox content system, we needed to use simple php include function calls to
render the header, footer, and other components of the page not under Symphony control. PHP in the view layer is a
relatively un-Symphony thing to do, but fortunately I had previously written an extension (EXSL Function Manager) to
help with just such a requirement. This extension converts PHP functions into EXSLT functions, keeping our XSLT
templates nice and clean while incorporating the needed external markup.
Andrew Shooner, Developer, Vine Street Interactive
[0204.png]
Overview
URL: http://publicculture.org
Developer: Craig Zheng
I think I remember hearing that most people who build and manage websites for a living spend their copious free time
catching up with the latest scholarly discourse on topics like globalization, capitalism, cosmopolitanism, and modernity.
As such, youre probably already intimately familiar with the journal Public Culture.
The journals website is a showcase of sorts for its content and for related news, events, and resources. Users can
explore Public Cultures recent archives, browse its contributors, and see artwork and photography that has appeared in
the journal. The site also features lots of detailed information about the journal (mastheads, submission guidelines, and
the like) along with news and events listings, a visual Books Received stream (powered by Readernaut), a host of web
feeds, and more.
Points of Interest
As a journal, Public Culture is dealing with loads of content that is inherently meaningful. Issues have numbers, publish
dates, and covers. Articles belong to issues, and have page numbers, authors, sometimes artwork. The journals
contributors can have bios, academic disciplines, affiliations, and can be linked to articles, artwork, news items, events,
and so on. Symphonys open content structure allows all of this data to be stored in bits that are most meaningful in their
particular context. For example, capturing page numbers means it can use those to build links to citation tools on the front
end.
The website features some interesting third-party integrations as well. Its search function is powered by Googles Custom
Search Engine (CSE)meaning it takes advantage of the search giants powerful indexing and algorithms, but receives
search results as XML that can be templated natively within the site. Its a seamless experience for users, and Google
takes care of all the heavy lifting.
There is also some integration with CampaignMonitor (CM), a service the journal uses to send email newsletters. If
youve ever had to design an HTML newsletter, you know what a hellish process that can be. But because of
CampaignMonitors HTML import tool and Symphonys flexible front end, the site simply uses an alternate template to
render newsletters for import into CM. What that means is that the journals staff never has to think about formatting HTML
emails. They just write a newsletter once in Symphony, and it is made available both within the website itself and as a
standalone HTML email (Figure 2-5).
Figure 2-5
[0205.png]
Developers Thoughts
Public Culture is actually the reason I found Symphony. I was a graduate student in anthropology at the time, and working
as a manuscript editor for the journal. I had a bit of experience with web development, though, and so when the journal
needed a new website, I volunteered my amateurish services.
I built the first version of the site using another (very popular) CMS. All throughout the development process, I grew
increasingly frustrated as I ran into inefficiencies and constraints over and over again. One of the reasons Id chosen the
system is that it allowed me to define the content types I needed (journal issues, articles, authors, and so on), but the
further I got the more I realized that the system itself was still remarkably inflexible. I couldnt even sort authors by last
name! And the more I learned about web development and web standards, the more I realized that this system really was
doing a lot of things poorly.
I started searching for alternatives and found Symphony just as we were launching the first version of the site. The
difference between the systems was so stark that I began rebuilding it almost immediately. Symphony was a breath of
fresh air, giving me the freedom to craft the site exactly as I wished I couldve the first time around. I had total control. I
defined the content that would drive the site, bit by bit, and Symphony allowed me to bring it all to life however I wanted. I
could create interfaces to browse issues by volume or authors by the first letter of their last name, and enable browsing
via the many rich relationships embedded in the content. I was able to implement a very systematic and structured design
system. And no matter what new problems or requirements arose along the way, Symphony always gave me a way to
solve them, easily and elegantly.
[0206.png]
Overview
URL: http://originaltravel.co.uk
Developer: Airlock
Original Travel is an award-winning travel company in the UK that provides custom, luxury vacations and tours all around
the world. If, like me, youve been holed up inside working feverishly for extended periods of time, be warned that visiting
this rich, visually stunning website is going to make you very, very sad.
The site allows potential clients to explore the hundreds of different trip possibilities on offerbrowsing by destination,
type of trip, time of year, etc. Every step of the way, visitors are provided with local travel tips and detailed information
about hotels and activities. Dedicated trip specialists for each region contribute to a company travel journal. The site also
features a shop (with checkout), and once a customer has booked a trip they can login and view their itinerary and other
documents online.
Points of Interest
Original Travels website is all about places (places I cant be, incidentally), and so its fitting that one of its most
distinctive features is a robust integration with Google Maps. When destinations and journal entries are entered into the
system, a map location field (provided by a Symphony extension) allows content editors to set their location simply by
placing a pin in a map. The data saved by that field is actually a pair of longitude and latitude coordinatesthe useful
bits, in other words. On the front end, visitors are then able to browse destinations using an interactive map, onto which
all of the different sets of coordinates in the system have been plotted.
Figure 2-7
[0207.png]
Original Travel also makes heavy use of Symphonys dynamic image manipulation capabilities. The sites many
gorgeous photos of tropical beaches and European villas that torture me so relentlessly can each appear in multiple
contexts, and for each context the design has different size requirements. These range from full-width (974x368) to promo
size (306x172) to thumbnail (160x90). Does that mean that for every image (and there are lots), editors have to create
several versions? No. They upload an image once and only once, and everything just works. How? The designer has
crafted the sites templates to specify what size images belong in which contexts, using a specially-crafted URL in the
image elements src attribute. Symphony takes care of the rest, dynamically resizing, cropping, or otherwise editing the
original and then caching and serving the resulting image.
Figure 2-8
[0208.png]
Developers Thoughts
Symphony allowed us to quickly build our data model directly from the wireframe blueprints, in a matter of days rather
than weeks. We modeled continents, counties, trips, hotels, activities, seasons, journal articles, testimonials and many
more (52 in total). We were able to let the client add start adding their content to these sections before the designers had
even finished designing the site! And because sections are easy to modify, we could react to evolving content
requirements as data entry progressed. This meant that by the time we came to build the frontend, we already had more
than half of the final content to style with. You don't get much more agile than that.
Nick Dunn, Head of User Experience, Airlock
[0209.png]
Overview
URL: http://connosr.com
Developer: Jean-Luc Thiebaut
Everyones got a passion, and for some people that passion just happens to be hard liquor. Whisky Connosr is a social
networking community built especially for enthusiasts of that coppery, distilled beverage.
The site has many of the features youd expect to find in a social networkmember registration, profiles, buddies,
activity streams. And there are tie-ins to existing networks as well. Member profiles, for instance, can incorporate Twitter
streams, and bottles of whisky can be liked via Facebook. But most of what makes this community work is totally unique
and hinges on its subject matter. Members can follow particular whiskies, review and rate specific bottles, and add
bottles to their personal whisky cabinet or wishlist on the site. On top of that, there is an active discussion board (The
Whisky Wall), a blog, an events section, and an impressive online whisky magazine called Connosr Distilled.
Points of Interest
Connoisseurs of any kind tend to be obsessed with details, and this enthusiasts social network revolves around several
quite specialized kinds of web content. Every bottle of whisky, for example, comes from a specific distillery, has a
particular water source and bottler, an age, an alcohol-by-volume ratio, and so on. Whisky reviews point to specific
bottles, and capture unique characteristics like the whiskys color and the reviewers overall rating of the bottle (Figure 29).
Figure 2-10
[0210.png]
This is a social network, though, and participation above all is the driving force. The site makes heavy use of Symphonys
ability to power unique interactions and user journeys by allowing all kinds of content to be submitted to the system from
the front end. From the discussions on The Whisky Wall to the sites thousand-plus reviews and its member profiles and
whisky cabinets, Symphony is helping the sites developers fuel avid participation among its thousands of members.
Developers Thoughts
[Waiting for developer quote]
Summary
In this chapter, weve toured a handful of Symphony-powered websites and web applications in the hopes of
demonstrating the breadth of the systems capabilities. We looked in particular at five different types of Symphony
projects: a personal site, a web/mobile app, a publication site, a business site, and a social network. There are many
other worthy candidates we might have exploredlike the high-demand media and contest sites that have been
developed for clients like BBC and Channel 4, or a software community like the Symphony website itselfbut well save
some of these examples for other parts of the book.
In the meantime, youre probably itching to just roll up your sleeves already and start exploring the system. Lets go get
you started.
Figure 3-1
[0301.png]
More often than not, these requests involve content. Either someone wants to get content from your site (like a visitor
trying to read your article), or someone wants to post content to your site (like your ex leaving a snarky comment about
your eating habits). In either of those cases, while processing the request, Symphony communicates with an underlying
database, in which all its content is stored.
So, essentially, Symphony is sitting on a server and handling various kinds of interactions between content stored on the
server and people who want to use that content. There's a lot more to it than this, of course, but we've got a dozen or so
chapters to cover the details more thoroughly. For now, it's enough just to have this rough overview of how Symphony
works. Now let's review some of the other concepts we've introduced in case they're new to you.
Web Servers
A web server, put very simply, is a computer equipped with software that allows it to respond to web requests. This can be
any kind of computer, from the laptop you have at home to the sleek, powerful machines that commercial web hosting
companies use. Of course, when you've got a website that you actually want to share with the world, you'll use the latter.
But most developers actually work with a combination of the twothey set up a local server (server software running on
their own computer) to build and test their sites, and then push to a remotely hosted server when their work is ready to
see the light of day.
Note
I highly recommend setting up a web server locally on your own computer, both for the purposes of this book and
for web development work in general. You'll be able to work faster and troubleshoot more easily. Later in this
chapter, after we discuss Symphony's server requirements, I'll provide some pointers on getting this set up.
Server Environments
Web server software is designed to handle requests and responses, but the applications that run on these servers have
to do all kinds of other stuff toothey need to run code, store and retrieve data, and so on. So a server has to be
configured to provide web applications with access to all kinds of other things, from programming language libraries to
software packages to databases. The sum of all thisthe web server software and everything it provides access tois
referred to as the server environment. Like animals and their habitats, web applications require specific kinds of
environments in order to function.
Note
configured... Taken together, these variables can account for significant differences from one server environment to
the next. Knowing the details of your server environment can save you a lot of time while troubleshooting, because
often it's in these differences that your problems will lie.
Databases
For most web applications, Symphony included, databases are a necessary part of the server environment. They provide
an organized and efficient way to store and retrieve massive amounts of complex data. Database software usually runs
alongside web server software, allowing web applications to connect and query their databases as needed.
Summary
I hope that reviewing these key concepts will make it easier for you to follow along with the rest of this chapter. If you find
any of the above unclear or confusing, though, it's probably a good idea to do a little more basic research on your own
before continuing. I'll do my best to fill in the gaps, but if you're going to be working with Symphony, you'll want to have a
pretty good handle on this stuff beforehand.
Note
For more information on servers, databases, and other web technologies, try:
How Web Servers Work: http://computer.howstuffworks.com/web-server.htm
Google Code University: http://code.google.com/edu
W3 Schools Tutorials: www.w3schools.com/
Nettuts Plus Basix: http://net.tutsplus.com/tag/basix/
Once you feel comfortable enough to begin getting into server environment details, read on.
Server Requirements
The first thing you'll need, of course, is a web server. Symphony requires Apache or Litespeed (though it's worth noting
that people have had success run-ning Symphony on other kinds of servers as well, like NGINX and even Micro-soft's
IIS). Whatever server software you use, it'll need to be able to rewrite URLs, so Apache's mod_rewrite (or whatever your
server's equivalent is) will have to be enabled.
Symphony is written in PHP, so your server environment will need to have PHP 5.2 or above installed in order to run it. In
addition, your build of PHP will have to have XML and XSLT support enabled because, as we've seen, Symphony leans
on these technologies heavily. Both extensions are already included with PHP, but while the LibXML extension is
enabled by default, the XSL extension needs to be enabled explicitly. Again, most commercial hosts have this turned on,
but if you're setting up a local server, you'll have to remember to activate the XSL extension yourself.
Finally, Symphony stores its content in a MySQL database. MySQL is one of the most widely used database systems
available and you'd be hard-pressed to find a web host that doesn't support it. You'll want to have a recent version,
ideally, but Symphony can work with versions as far back as MySQL 4.1.
That's all it takes. Im not kidding.
Requirements Summary
An Apache or Litespeed web server, with mod_rewrite module or equivalent
PHP 5.2 or above, with the LibXML and XSL extensions enabled
Decisions, Decisions
Local Versus Hosted
The first thing you need to decide is where you're going to install Symphony. For production sites, of course, you'll use a
web host. But for development and testing, and certainly for the purposes of this book, I recommend you take the extra
time to set up a local server environment on your own computer (if you don't already have one). It'll make things much
easier for you in the long run. I provided some pointers in the last section to get you started.
If you do choose to install on a remote server, there are a few things you should be aware of.
If you need to transfer files from your computer to the server, youll need an FTP client. Thankfully, there are lots of free
FTP clients available for all the major operating systemsthe cross-platform Filezilla, Cyberduck on Mac, SmartFTP on
Windows, gFTP on Linux, and many others. If you need to execute commands using the command line, youll need
secure shell (SSH) access to your server, which isnt always available in shared hosting environments.
directory.
2. Extract the package.
3. Optional. When starting with a completely clean system (which we will be for this book), you should delete the
workspace/ directory.
4. Move the contents of the extracted directory to the desired location on your server. Note that you dont want to
include the package directory itself (the one named
symphony-n.n.n
where
n.n.n
want to include its contents. In other words, you want the index.php file right in the directory where you want to run
Symphony.
5. Use your file browser or FTP client to temporarily set permissions on the root directory (the one you just installed to)
and the
symphony/
directory to
777
directory to
777
(read, write, and execute for all). Then set permissions on the
workspace/
and tell your client to apply the changes recursively (to all subfolders). Don't worry, well undo this
wget http://symphony-cms.com/download/releases/current && unzip symphony-n.n.n.zip && rm symphony-n.n.n.zip && mv symphony-n.n.n/* . && rm
curl -L http://symphony-cms.com/download/releases/current > symphony.zip && unzip symphony.zip && rm symphony.zip && mv symphony-n.n.n/*
Where
n.n.n
3. Optional. When starting with a completely clean system (which we are for this book), you should delete the
workspace/ directory:
rm -R workspace
Don't worry. Well undo this step and tighten up permissions after installing.
Using Git
1. cd into parent directory of the directory where youd like to install Symphony (for example, if youre installing into your
servers root at public/html, you want to cd into public/).
2. If the directory you want to install into exists, you have two options: A) Make sure youve safely backed up its contents
and emptied it, and then remove the directory (in the example above, youd execute the command rmdir html). B) If
there are contents inside it that you cannot delete, you can clone the repository into a subdirectory, and then move all
the files and directories (including the hidden .git directory) back up into the main directory.
3. Clone the Symphony Git repository using the following command:
git clone git://github.com/symphonycms/symphony-3.git directory
Where directory is the name of the directory into which youd like to install Symphony. For example, if youre
installing to your servers web root at public/html, youll want to use html in the above command.
4. cd into your installation directory:
cd directory
Where directory is the name of the directory into which you just cloned the repo
5. Grab the default extensions:
git submodule init git submodule update
6. Optional. If youve decided to include a starter package rather than start with a clean system, clone the package into
your workspace directory:
git clone git://package-git-url workspace
Where package-git-url is the location of the starter packages Git repository
7. Set temporary permissions for the install script:
chmod 777 symphony . chmod -R 777 workspace
Don't worry. Well undo this step and tighten up permissions after installing.
Note
Creating a Database
Creating a database for Symphony to use is a fairly simple step, but in order to proceed youll need to know your MySQL
username and password. If you're installing on a local server, you will have created these yourself. If you're installing on a
web host, they may have been assigned by your hosting provider, or you may have created them using your servers
control panel.
You'll probably have several different options for creating a MySQL data-base, including phpMyAdmin, the command line
MySQL client, and web host control panels. The latter are usually fairly straightforward and well-documented, so I'll just
cover the former two here.
Using phpMyAdmin
1. Log into your phpMyAdmin interface.
2. Youll see a field on the home page labeled Create new database. En-ter a database name (note this for the next
step), and from the Collation dropdown, select
utf8_unicode_ci
db_name
with a suitable database name, like symphony. You should see a message telling you
Your Website
Figure 3-2
[0302.png]
Your Server
Figure 3-3
[0303.png]
Root Path: This should be automatically detected and pre-filled for you.
File Permissions: Select the desired permissions settings for files created by the system.
Directory Permissions: Select the desired permissions settings for directories created by the system.
Your Locale
Figure 3-4
[0304.png]
Region: Select the region of the world your website is based in.
Date Format: Select a date format to be used in the admin interface.
Time Format: Select a time format to be used in the admin interface.
Your Database
Figure 3-5
[0305.png]
[0306.png]
Username: Enter the username youd like to use to access Symphonys admin interface.
Password (and Confirm Password): Enter the password youd like to use to access Symphonys admin interface.
First Name: Enter your given name.
Last Name: Enter your family name or surname.
Install Symphony
Figure 3-7
[0307.png]
rm install.php
Second, be sure to tighten up the folder permissions you adjusted during setup. Exact settings will depend on your server
environment, but the permissions on your root directory and your symphony/ directory should be fairly restrictive (try
something like 755). Then set manifest/ and workspace/ to 775 (make the workspace/ permissions recursive, so they
apply to its subdirectories as well).
Figure 4-1
[f0401.png]
So if the urge to poke around a bit is too much for you to bear, feel free to do so. Ill wait here.
Whether you decided to explore on your own or not, it wont be long before you realize that you can save yourself a lot of
time if you get to know the lay of the land first. This may seem like a tedious step, but then again its always better to have
a map in your pocket than not, right? Well this chapter is that map, your birds-eye view on all things Symphony.
Well begin with a cursory glance at the admin interface, or back end, just to give you an initial point of reference
something to anchor your mind as we batter it with new ideas and information. Then well set about exploring the system
from three angles:
1. For starters, we'll review what the system looks like functionallythe working elements that allow you to define,
manage, and deliver content.
2. Then, we'll dive in visually to explore Symphony's admin interface in detail.
3. Finally, we'll have a look at how Symphony is represented physically on your serverthe directories and files that
comprise it and what they do.
These three overviews should provide you with a strong foundation for the rest of the bookwhether youre a total noob
or an experienced web developer, a designer or a programmer, a visual thinker or a conceptual one, or none of these
things.
Figure 4-2
[f0402.png]
The left side of the navigation menu is where you manage all the content that will power your websitebe it blog posts,
portfolio items, products whatever. Because Symphony allows you to define those content types yourself, this part of
the menu will vary from site to site. Thats why I referred to the image above as a sample menu. The right side of the
navigation menu is where you manage all the elements that structure your website and its behavior (its blueprints, if you
will), and anything else related to administering the system. The two submenus you see hereBlueprints and System
form the backbone of Symphonys admin interface. Everything about your website, from the shape of its content and
interactions to its URL schema and design, will be defined and determined here. Lets quickly walk through those
submenus now. If youre looking at the Symphony admin interface in your browser as you read this, hover over the
Blueprints item. Otherwise, you can refer back to Figure 4-2. Either way, you see the following submenu items under
Blueprints:
Views are used to build out your websites front end. They determine where visitors can go to access your website,
and what theyll see when they get there.
Sections are used to define and outline the types of content youll be managing.
Data Sources are used to filter and channel content to your front end.
Events are used to capture and save input submitted from the front end.
Utilities are used to manage reusable bits of template code.
Now, hover over the System menu item (or glance at the System submenu in Figure 4-2). It contains the following items:
Users are accounts that have access to the admin interface.
Settings allows you to adjust various system settings, such as date and language preferences.
Extensions can add important functionality to your system, and can be enabled, disabled, and uninstalled here.
Dont worry if all of this is a bit of a blur at the moment. Whats important is that your mind has something visual to anchor
it as we move on to discuss all of these new concepts in greater detail.
Figure 4-3
[f0403.png]
Lets take a look at how Symphonys internal structure maps onto these broader, functional layers:
The content layer consists of sections and fields. Together, these enable you to define very precisely what kinds of
content you'll be managing and how you'll capture and store it.
The interaction layer consists of views, data sources, and events. These allow you to specify what requests your site
will respond to (i.e. its URL schema), what it will do with them, and what data it will send back.
The presentation layer consists of view templates and utilities. These are used to format the data your site delivers
to the user.
Whenever a visitor lands on your website, these three layers work together in harmony:
1. A view responds to the visitor's request, kicking into action any data sources and events that are attached to it.
2. The data sources then fetch content from your sections (or from elsewhere, for example an RSS feed), and send it
back to the view.
3. The view then uses its template (and any attached utilities) to format the data and display it.
You can see a flowchart of this process in Figure 4-4:
Figure 4-4
[f0404.png]
Now lets take a quick look at each of these layers and their components in turn.
Figure 4-5
[f0405.png]
As you can see, every section is comprised of one or more fields, and each individual piece of content (each entry in a
section) is made up of data corresponding to those fields.
Lets say youre using Symphony to launch a web-based magazine. Youd start by asking yourself, What kinds of content
do I need to be able to create and manage? Things like issues, articles, and authors might come to mind. These would
be your sections. Then, for each of these, youd ask, What do these things look like? What pieces of data do they
contain? For something like issues, your answer might be: each issue will have a title, an issue number, a description, a
cover image These would be your fields. Having defined that structure, every new issue you createdor, in Symphony
terms, each new entry in the issues sectionwould be made up of these same fields.
Note
If you've ever worked with databases, sections would be analogous to tables, fields to columns, and each entry
would be a row. For object-oriented programmers, sections would be like classes and fields like class properties,
and each entry would be an object instance.
As weve mentioned several times, Symphony gives you a completely blank slate when it comes to your content layer; it
doesn't make any assumptions at all. Even if you download a copy of Symphony that has some default sections set up,
theres nothing stopping you from deleting all of them and starting fresh. With sections and fields, you can create and
manage any kind of content you likefrom articles and blog posts to yarns and zoo animals.
Theres a bit more to all of this, of course. For example, youll often need to create relationships among your sections (e.g.
giving your magazine articles an author and placing them in a particular issue). Youll also need to change the structure
of your sections from time to time, even after theyve been created and populated with entries. And there are many
different types of fields, each with its own configuration options and its own ways of storing and retrieving data. But well
get into all that in Chapter 5. First, lets talk about what Symphony allows you to do with your content once youve got
some.
Figure 4-6
[f0406.png]
It starts on the front end, with views. In Symphony, you use views to build an interface that will respond to visitors URL
requests (whether they come from a web browser or via some other sort of client application like a feed reader). In other
words, views are the answer to the question, Where do I want my visitors to be able to go, and what do I want to show
them when they get there?
Each view is configured to respond to a certain request (or set of requests), at which point it executes any data sources
and events that are attached to it (more on that in a moment). The data sources (and sometimes events) will return a
bunch of content, which the view will then template for display in the browser (or for consumption in some other format).
So the view is a middleman of sorts, like a waiter taking and delivering orders in a restaurant. Data sources, in that
scenario, would be the dishes. They may have a very technical-sounding name, but they are exactly what youd think:
sources of data for a view. Data sources can grab content from all sorts of places (your sections, other websites, your
systems user info), and can have any number of conditions, filters, and other directives specified. Every data source, in
other words, has its own unique recipe for delivering content to your front end.
Note
If youve ever worked with databases, youll probably find it helpful to think of data sources as being akin to
queries. Youre just asking Symphony to fetch you a set of data from a particular source that meets certain
requirements, and to limit and sort the results as requested.
This may sound a bit overwhelming, especially if youre accustomed to using systems that make these kinds of decisions
for you, but hopefully by now youre beginning to see some of the tremendous potential inherent in this structure.
Because Symphony doesnt make assumptions about how you want your visitors to interact with your content, youre free
to set up your views and data sources to do anything youd like. Want your visitors to be able to go to
http://yoursite.com/archive and see a reverse-chronological list of your magazines issues, grouped by year? No problem.
Rather have them grouped thematically and then sorted by issue? You can do that too. Want to serve an RSS feed at that
URL instead? Again, easy as pie.
Events are the flip side of the interactive coin. If data sources enable content to be fetched and displayed on the front end,
events allow data submitted from the front end to be saved into your sections. If your magazine permitted comments to be
submitted by visitors, for instance, an event would do the job. Member-driven Symphony websites like Connosr.com and
the Symphony website itself rely heavily on events because users can submit everything from forum posts and reviews to
extension packages, all from the front end.
As you might suspect, theres a lot more to all of this, and at the moment youve probably got more questions than you
know what to do with. Dont worry. Well have an in-depth look at views in Chapter 6, and then at all the different kinds of
data sources and eventsand the options available for eachin Chapter 7. For now, if youve got a rough sense of how
the interaction layer works in Symphony, youre in good shape.
Figure 4-7
[f0407.png]
Every view in Symphony has a corresponding view template. Because the data thats delivered to your views is raw XML,
what the view template needs to do is transform that XML into a format that your visitors can use. Most often, its turned
into (X)HTML for display in a browser, but your view templates can actually produce almost any format at allRSS or
Atom-flavored XML, plain text, comma-separated values (CSV), PDFs even JavaScript or CSS.
View templates can accomplish this sorcery because theyre written in XSLT (Extensible Stylesheet Language
Transformations), which youll recall is a templating language developed precisely for the purpose of transforming XML.
Fortuitous, no? Rather than inventing some system of arcane pseudo-tags, Symphonys presentation layer allows you to
leverage a widely-used, powerful, open standard.
Among the many, many benefits of XSLT is that it makes it easy for you to organize and reuse code. Programmers know
how important it can be to pull out snippets of code that perform common tasks and to reuse them. And designers know
how important it is to produce markup thats consistent and easy to maintain. Utilities are independent XSLT stylesheets
that can be dynamically included by view templates and thus reused, remixed, and recycled anywhere on your website.
Perhaps the most common use of utilities is the creation of a master layout stylesheet, responsible for outputting all the
markup that will be used universally throughout your front endheader, navigation, and footer, for example. Another
common usage is for utilities to contain snippets of template code that can be used over and over in many different
contexts. Lets say, for instance, that you wanted your magazine website to make heavy use of Microformats.1 You could
create a Microformats utility that would used to output hCalendars wherever you were displaying a date, hCards
wherever you were displaying author profiles, and so on.
Though fairly simple conceptually, Symphonys presentation layer is remarkably powerful thanks to the capabilities it
inherits from XSLT. That said, for many people, its also the toughest part of the Symphony learning curve. Have no fear,
though, because Chapter 8 is going to tell you everything you need to know about templating in Symphony, and may
even turn you into an XSLT master of unparalleled guile and charm (if not actual skill).
1
. Microformats are a set of simple, open formats that allow you to embed meaningful data in markup that otherwise
Figure 4-8
[f0408.png]
The admin interface is designed to be easy to navigate and easy to use. Wherever you happen to be in Symphonys back
end, and whatever you happen to be doing, youll see the same basic layout. A title bar (1) identifies the project and the
current user. A simple, horizontal menu (2) allows you to navigate through the back end. And the main content area (3) is
used to display the various tables and forms that youll use to manage your website and its content.
Functionally speaking, the admin interface provides access to three basic areas. Well review those quickly now.
Content
The content area, on the left side of the navigation menu, can consist of any number of submenus that allow you to
manage your content entries. When you create a section, you assign it to a navigation group. Each navigation group
becomes a submenu in the content area, and each Section belonging to that group becomes an item in that submenu
(unless its hidden, which well discuss in Chapter 5).
Confused? Well lets go back to our magazine example. Imagine you were to create sections for issues and articles, and
assign both sections to a navigation group called Content. Then imagine you created three more sectionswriters,
photographers, and editorsand assigned each of them to a navigation group called Contributors. What youd end up
with is a menu that looked like Figure 4-9:
Figure 4-9
[f0409.png]
Clicking any item in one of these content submenus will take you to the index page for that section. A sections index will
display a paginated table of all content entries in that section. So, using the example in Figure 4-9, clicking Content and
then Articles would allow you to browse all article entries in the system. Each column in the table will correspond to one
of the sections fields (you get to decide which fields display in the table).
Youll notice that each entry in the index table is linked. Clicking the link will bring you to the entry editor, a form that
enables you to create and edit entries. What this form looks like, of course, depends entirely on the fields youve added to
your section, and how youve chosen to lay them out. Well explain how all that happens in Chapter 5.
Note
The index/editor paradigm is a convention used throughout the Symphony admin interface. All of your content
sections, and all system components (like views and data sources), have indexeswhere you can view all the
items in paginated tablesand editorswhere you can fill out forms to create and update individual items.
Blueprints
The Blueprints submenu allows you to manage all of the functional building blocks discussed above: views, sections,
data sources, events, and utilities. Together, these determine the structure and behavior of your entire website, hence the
term blueprints. Were going to cover each of these elementsalong with the interfaces for managing themin great
detail in Chapters 5 through 8, so for now lets move on.
System
The System submenu contains items that allow you to customize and fine-tune your copy of Symphony. By default, it
consists of three items: Users, Settings, and Extensions.
As mentioned above, a user in Symphony is someone who has access to the system and is allowed to log in to the back
end. Going to System > Users will take you to the user index, where youll see your own user account and any others
youve created. Clicking your name will take you to the user editor, where you can adjust your user details, change your
password, and so on. Well discuss users in more detail in Chapter 9.
Symphonys Settings page is a simple form that allows you to manage a few basic system configurations like your
websites name, the default language for the admin interface, and so on. If you install any extensions that have settings of
their own, youll be able to manage those here as well. Symphony only exposes the most commonly used settings in the
admin interface; many more are available in a configuration file, which well talk about in the next section.
The System menu is also where youll find the area for managing extensions. Because a central tenet of Symphonys
philosophy is to keep the core of the system lean and efficient, extensions are a vital part of any Symphony website. Much
of the functionality that will make your website unique and useful will be provided by the rich ecosystem of extensions
built by the Symphony team and by the community. All of your field types and your data source types, for example, are
provided by extensions.
At System > Extensions, you can enable, disable, and uninstall extensions, and monitor the status of the extensions
youre using at any given time. Well cover how to work with extensions more fully in Chapter 9.
Physical Footprint
Depending on how technically inclined you are, you may not spend very much time at all exploring the various directories
and files that live on your server and keep Symphony humming along smoothly. But, whether youre doing periodic
backups, fine-tuning advanced configuration options, or troubleshooting a problem, knowing how Symphony is structured
physically could turn out to be a lifesaver someday.
Folder Structure
When you upload and install Symphony, you create on your server a hierarchy of directories and files that looks like
Figure 4-10:
Figure 4-10
[f0410.png]
Many of the files at the root of your installation are self-explanatory. The index.php file, as you might guess, is the main
switchboard for your Symphony site. All requests, front-end and back-end, are routed through it. The update.php file has
an equally obvious use: you run it when you want to update from one version of Symphony to another. When Symphony
is installed it also creates a file called .htaccess (depending on your operating system, it might be hidden from view). This
file contains server-level directives that help with routing URL requests and is a common place to look when your site
isnt behaving as expected.
In addition to these top-level files, Symphony will create several directories. Lets look at those now.
Extensions
This one is simple enough. Its where your extensions live. Each individual extension has its own directory inside the
extensions/ folder. When you want to install a new extension, simply place it in this directory, and youll be able to enable
it from within the admin interface.
Note
Symphony auto-includes extensions by predicting their folder names based on the names of the extension classes
in PHP. If youre ever trying to install an extension and its not appearing in the back-end, one of the first things to
check is that the extensions folder is named correctly.
Install
The install/ folder contains the files necessary to run Symphonys installer. Once youve successfully installed Symphony,
this folder should be removed.
The Manifest
In shipping, the manifest is a document that contains a log and description of all the cargo and passengers on board a
ship. The idea is that most of what you need to know about a ship can be gleaned from looking over its manifest.
Symphonys manifest/ directory is named in that same spirit. Most of what you need to know about a particular installation
of Symphony can be found in the various files in its manifest.
The manifest contains your sites cache, its configuration files, its system logs, and its temporary directory. It also contains
your extension configuration. In other words, all the system information specific to your website can be found here (as
opposed to build and content information, which can be found in the Workspace).
Inside the manifest folder is a config directory. This directory contains XML configuration files, which you can edit directly
in lieu of, or in addition to, using the Settings page in the admin interface. Many configuration options are available in
these files that are not accessible from the Symphony back end. Well talk more about those in Chapter 9.
Finally, whenever youre troubleshooting problems with your Symphony installation, a logical first place to look is in
manifest/logs/. There youll find system logs detailing all manner of server-level events. Youll want to have the info handy
whenever you ask for help with Symphony.
Note
If you ever want to customize Symphonys internal templates (like the default view template XSLT, or the default
system error pages), you just need to create a directory within manifest/ called templates/ and copy into it
duplicates of the files you find in symphony/templates/. The files in manifest/ will override the default system
versions, and you customize them to your hearts content.
The Workspace
The workspace/ directory contains all of your project-specific files. By default, the workspace will store data sources,
events, sections, views, and utilities. Because all of your websites blueprints are file-based and stored in the workspace,
Symphony projects can be very elegantly version-controlled, and integrated structures can be easily shared, reused, and
remixed between websites. Symphonys admin interface will dynamically accommodate changes to files in the
workspace, even if those changes arent propagated from within the back end itself.
In addition to your blueprints, you can use the workspace to store files uploaded via upload fields in your entries, and
developers will often store other assets here as well, like CSS and JavaScript files or template images. As long as the
default subdirectories are left intact, users are free to create any directory structure they like within the workspace/ folder.
Example
Nomenclature
In Symphony 2, views were known as pages. Pages was actually a misleading term, though, because one page in
Symphony could actually power an entire front-end interface that rendered any number of web pages to a visitor. It
turned out to be doubly confusing because most other content management systems have a page concept as well
wherein pages are containers for static content. The fact that Symphonys use of pages went against this widespread
convention probably caused some confusion and frustration for new users, so with version 3 the term was changed to the
more appropriate views.
File Structures
In Symphony 2, sections and views were stored in the database rather than in XML files in the workspace. As a result,
version control and collaboration was much more tricky with Symphony 2.
Also, in Symphony 2, the configuration was stored in a single PHP file in manifest/, rather than two separate XML files.
Splitting the configuration into two files for version 3 makes it possible to move the database configuration to a more
secure, inaccessible location on the server.
In Symphony 2 it was not possible to override Symphonys default internal templates as described above.
Database
Symphony 2 stored lots of structural data (section schemas, page configurations) in the database alongside actual
content. Symphony 3, on the other hand, moves that structural data into files, as described above.
Also, Symphony 3 adopts a much more meaningful table-naming schema, sym_data_section-name_field-name rather
than sym_entries_data_field-id. So where, in Symphony 2, youd have a table called sym_entries_data_42, in Symphony
3 its called sym_data_articles_title. This makes working directly with the database much easier.
Extensions
Many things became extensions in Symphony 3 that were built into the core in version 2:
Field types. In Symphony 2, there were core field types, a set of 6 field types that were bundled with the core and couldnt
be altered or removed. Additional field types could be added as extensions. In Symphony 3, though, all field types are
extensions, meaning theyre all treated equally and can be swapped and replaced at will.
Data source types. In Symphony 2, there were only five data source types. Custom data sources could be written in PHP,
and extensions could provide their own individual data sources, but it wasnt possible to provide new types that users
could use when creating data sources. In Symphony 3, all data source types are extensions, and extensions can provide
new data source types.
Event types. In Symphony 2, there was only one event type: the section saving event. It was possible to author custom
events, but not to create other kinds of events from within the admin interface. In Symphony 3, however, it is possible for
extensions to provide additional event types.
Admin Interface
Figure 4-11
[f0411.png]
In Symphony 2, all navigation submenus were left-aligned, and Events, Data Sources, and Utilities were grouped
together on a single back-end page called Components, which was accessible in the Blueprints menu. In Symphony 3,
as weve seen, each of those is split out into its own separate index page.
Summary
Weve taken a whirlwind tour of Symphony, inside and out, to give you a sense of the structure and scope of the system
before we start having fun and getting our hands dirty. Weve reviewed the systems functional anatomy, or the various
elements that it uses to enable you to create, manage, and deliver content on the web. Weve also walked through the
back-end admin interface to give you an idea of where all the functional pieces are located and how you can find them
and work with them. We looked quickly at the files and folders that comprise Symphony on your server, and explained
what most of them do so that you know where to look when you want to back up your data or troubleshoot a problem.
Finally, we covered the key differences between Symphony 2 and Symphony 3, in case you ever find yourself needing to
work with the older version.
Now that youve seen the roadmap, and have a rough sense of how Symphony works, lets go have some fun!
Chapter 5: Content
What's In This Chapter
Introducing our first Symphony project
About content modeling
Understanding content in Symphony
Working with content in Symphony
Let's build a website, shall we?
Over the course of the next few chapters, we're going to whip up a simple but functional blog. Well proceed slowly,
building the site one layer at a time so that along the way we can stop to elaborate on important concepts and tasks as
they arise. That means youll still have to stomach my long-winded explanations, but at least theyll be broken up into
smaller doses (and youll get to do some fun web building in between).
The first thing youll need to do is tell Symphony what kinds of content you want to manage. And though you probably
already have a pretty good idea of what you expect to find in a blog (things like posts and comments, for instance), there's
more to it than just naming them. You have to figure out what they're going to look like, how they'll behave, and how you
want the system to handle them. The process of answering these sorts of questions is called content modeling, and it
shapes the very foundation of a content-driven website.
So well start by talking a little bit about the general practice of content modelingwhat it entails, how it works, and what
you'll need to look out for. Then we'll formally introduce you to all of the elements that make up Symphony's content layer,
and as we begin building your blog, you'll see firsthand what it takes to model and manage content in Symphony. By the
time we finish the chapter, you'll be comfortable defining content and working with the content layer on your own, and
your new blog will have a rock solid foundation.
Let's start with a teaser exercise.
1. Point your browser to Symphony's admin interface.
2. Wink coyly at the screen and whisper, Hey there, sexy. (What? I did say "teaser").
3. Navigate to Blueprints > Sections, and click the green Create New button. You'll see a page that looks like Figure 51.
Figure 5-1
[f0501.png]`
4. Under "Essentials," enter Blog Posts as the name and Content as the navigation group (don't worry, I'll explain this
later).
5. To the right, under "Fields," youll see the section fields tool. Click the Add Field button. A drawer will open
displaying a set of field types. Click Text
6. A panel will appear for configuring your new field (Figure 5-2). Just enter the Title as the name, and select "Single
Line" in the size dropdown. Leave the remaining items untouched.
Figure 5-2
[f0502.png]
7. Click Text again to add another text field to your section. This time, enter Body as the name, and in the size
dropdown, choose Large Box. Leave the remaining items untouched.
8. Click Create Section.
Well done. Youve just created your first section, essentially telling Symphony that you want to manage a type of content
called Blog Posts, and that each of its entries should have a title and a body.
At this point, you could actually already begin creating blog posts in the system. See for yourself:
1. In the navigation menu, under "Content," click "Blog Posts."
2. You'll see an empty table, because we've not yet created any entries. Click the green "Create New" button.
3. You'll see the entry editor for your new section (Figure 5-3). Go ahead and fill in the form with some sample info.
Figure 5-3
[0503.png]
4. Save the entry, and navigate back to Content > Blog Posts. You should see the entry you just created listed there.
Easy, huh? Now, Im sure youve got all kinds of great ideas on how we can make these blog posts more interesting, but
for now let's hold off until you've got a firmer grasp on how all of this actually works.
Sections
First up are sections, the fundamental building blocks of a Symphony website.
Sections define the content you can manage. Creating a section and adding fields to it enables you to start producing
content entries. The section, and the fields it contains, define what the entries will look like and how and where theyll be
managed.
Sections define your publishing interfaces. For each section, Symphony creates an area in the admin interface for
managing its entries. Theres an entries index, or a table view for browsing and managing them in bulk, and an entry
editor for creating and updating individual entries. Sections are added to the navigation menu so you can access these
interfaces (unless you choose to hide the section).
Though Symphony creates each sections entry editor view automatically, the section itself defines how it will be
structured (well see how below). Obviously, the fields contained in a section determine the form elements that you see
(Figure 5-4), but you can configure the layout and organization of these elements.
Figure 5-4
[f0504.png]
Sections organize your content. All entries in the system are naturally grouped by section. Later on, when you need to
fetch content entries or process data submissions from the front end, you'll do so by section.
You can view and manage the sections youve created at Blueprints > Sections.
Fields
Fields do a lot of the heavy lifting for sections. Its fields that give a section its shape, store its data, and determine its
output.
Fields capture discrete bits of data. When youre creating an entry, youre not just dumping its content into some abstract
container. Every entry is made up of one or more fields, and its the fields that capture the actual data, piece by piece.
Fields validate and store data. Each field is responsible for storing the content its captured. This means that individual
fields can use their own rules to validate, transform, and save their data.
Fields output your data for templating. When your entries are passed to the front end, its the fields that are responsible for
handling and outputting their own data.
Because fields are the primary data handlers, they're used throughout the system for fetching, filtering, sorting, and
outputting content.
Once you add a field to a section, you can configure how that individual field will handle all of these taskshow and
where it should be displayed in the entry editor, what rules it should use to validate its input, if it should be displayed in
the entry index, and so on.
Field Types
The actual options you get when youre configuring a field, and the way it captures, stores, and handles its data, are
determined by its type.
Field types define how fields capture data. A text field, for example, gives you either a text input or a textarea, depending
on its size. A select box field gives you a dropdown menu. A checkbox field gives you wait for it a checkbox. There
are field types that give you more advanced form elements too: calendar date pickers, maps, sliders, autocomplete
inputs, and more.
Field types define how fields validate and store their data. The number field type will only accept digits, for example. The
map location field stores the chosen locations as coordinates. The date field type accepts textual date strings and stores
them as timestamps.
Field types determine how a field's data is output. The title field in our Blog Posts section, for example, being a text field,
would output its content like this: . A date field, on the other hand, would give us something more appropriate for the kind
of content its meant to capture: 2010-12-21.
Field types are provided by extensions. This is one of the primary reasons that Symphony is so flexible. Instead of limiting
you to a handful of common field types like text, date, select box, checkbox, and so on, any number of specialized field
types can provide whatever functionality you might need. Well talk more about working with extensions in Chapter 9.
Note
Field types also determine how a field can be filtered. Each field type has its own filter rules, so while text fields can
be tested against phrases, for instance, date fields can be tested relative to other dates (e.g. earlier than or later
than). Well discuss filtering in much more detail in Chapter 7.
Relationships
Very often, the various kinds of content were modeling for a website are somehow related to one another. The blog were
building, for example, should support commenting, and each entry in the Comments section will need to be linked to a
specific Blog Post entry.
Content relationships can make websites and web applications tremendously robust, allowing you to organize and
browse entries via their relationship to other entries.
Relationships in Symphony are managed via fields. There are a handful of specialized field types that can be used to
create and manage relationships. Adding one of these fields to a section will enable you to create relationships between
entries in that section and entries in whatever target section you choose.
[This part of the system is still being designed, so the remainder of this section will have to be filled in once its complete]
date. And if we want to be able to assign them to a category, well need a category field that creates that relationship.
Finally, lets add a checkbox to denote whether the entry is published or not, this way we can have unpublished drafts.
That wasnt too difficult, was it?
Comments are easy too. When visitors submit comments, well want to capture their name, email address, and the
comment itself. Well also want to record the date and time. A field pointing back to the associated blog post should round
off this section.
As for categories, lets just say each category will have a name and a description. We wont need much more than that.
So heres what our content structure looks like at the moment:
Blog Posts
Comments
Categories
Title
Author
Name
Body
Email
Description
Publish Date
Comment
Category
Date
Published
Post
Simple, but it will do the job. Now lets go build it.
Can you apply text formatters to the content? A WYSIWYG editor, for instance, or a syntax like Markdown?
How will filtering and sorting be handled? Text fields, for example, wont sort numbers correctly. Relationship fields
actually store entry IDs and so filtering and sorting by those might not work as youd expect.
What will the fields XML output look like?
Quite a bit to keep in mind. And whats more, once a fields been added to a section, you cant switch between types. So
making informed choices at this stage is important. You wont want to add too many content entries until youre confident
in your section structure, because swapping field types means removing the original field and losing all its data.
All that may seem intimidating, but like many things in Symphony, a lot of this can be figured out with good old common
sense. The system comes bundled with eight basic field types, most of which are self-explanatory. Dozens more are
available as extensions, but for now well just review the basic ones.
For each field type listed below, Ill outline:
what form element it provides for capturing data in the entry editor
how it stores its values
whether/how it validates its input
whether/how it can be used to filter entries
whether/how it can be used to sort entries
what some example output looks like
whether/what special configuration options are available
Checkbox
Form Element: checkbox
Stores: One of two values: Yes or No
Filter: by value
Example Output: Yes
Configuration Options: whether field should be checked by default
Date
Form Element: text input
Stores: timestamp
Validates: as date or timestamp
Filter: by year, date, or timestamp
Sort: by date
Example Output: 2012-12-21
Configuration Options: whether to prepopulate with current date
Number
Form Element: text input
Stores: number
Validates: as integer
Filter: by value
Sort: by value, numerically
Output: 0
Relationship
Form Element: select box
Stores: an entry ID
Validates: as entry ID from linked section
Select Box
Form Element: select box
Stores: a textual value
Validates: as one or more values among preconfigured options
Filter: by textual value
Sort: by textual value
Example Output: option 1
Configuration Options: what static/dynamic options to provide, whether to allow multiple options to be selected
Tag List
Form Element: text input with suggestions list
Stores: a textual value
Validates: as comma-delimited values
Filter: by items textual value
Example Output: Tag 1Tag 2
Configuration Options: where to draw suggestions list from
Text
Form Element: text input or textarea
Stores: a textual value
Validates: against any regular expression pattern (URL and email address are preset options)
Filter: by textual value or regular expression
Sort: by textual value
Example Output: Sample Text
Configuration Options: text formatters to apply, size of field
Upload
Form Element: file upload
Stores: the file, at designated location, and the file name, path, and size
Validates: as file type (image and document are preset options)
Filter: by file name
Example Output: image/png44kb
Configuration Options: upload location
User
Form Element: select box
Stores: a user ID
Validates: as user ID
Filter: by user ID or user name
Sort: by user ID
Output: Full Name
Thats a lot of info, but all pretty straightforward, actually. Well be able to choose our field types without much deliberation
at all. Our Blog Posts title and body, we know, are text fields. The publish date, clearly, will be a date field.
Published is going to be a simple checkbox, because we only need to be able to mark entries as published or not
published. And category has to be a relationship field pointing to Categories.
For Comments, author, email, and comment will all be text fields. Date will be a date field, of course. And Post will
Figure 5-6
[f0506.png]
Name is the name used to reference the field internally. Its what youll use when choosing the field for filtering, sorting,
and output, and is used an as element name in the fields XML output.
Publish Label is optional, and is used when the text you need to display with the fields form element is more complex or
explicit. You might have a date field, for instance, whose label needs to read Enter the date to publish this entry, but you
dont want the system to use that unwieldy phrase everywhere.
Show column tells the system whether to display the fields value in the sections entry index.
Make this a required field tells the system whether to require that the field have a valid value before saving.
The rest of the options you see above are specific to the text field type. We wont get bogged down with all of that here,
but you might want to take a quick glance at Appendix B for a description of the configuration options provided by each
field type. For now, lets finish configuring your Categories.
First, configure the name field:
1. Enter Name into the Name field
2. In the Size dropdown, select Single Line
3. Check the box next to Make this a required field
4. Leave the rest of the options in their default state
Now well add the description field:
1. Click Text again in the field types list to add another text field
2. Enter Description into the Name field
3. In the Size dropdown, select Medium Box
4. Uncheck the box next to Show column
5. Uncheck the box next to Output with handles
6. Click Save Changes
Lets do the Comments section next:
1. Go to Blueprints > Sections (or in the notification bar that appeared at the top of your screen when you saved this
section, click the View all link)
2. Click Comments in the sections index
3. In the fields tool, click Add Field
Lets take a closer look at what the fields tool looks like once youve got a bunch of fields in it (Figure 5-7):
Figure 5-7
[f0507.png]
Each of the fields youve added is listed on the left side in a sort of tab. The tab contains the fields name and field type
so you can see at a glance what your section looks like.
If you hover over these tabs with your mouse pointer, youll see a small delete button appear. This is how you remove a
field from your section.
To reorder fields, simply click the field tab and drag it up or down. Try reordering the fields in your Blog Posts section and
saving your changes.
Whichever field is listed first is treated by Symphony as the sections primary field. This means its used when referencing
an entry in the admin interface (for instance, in the entries index for that section, itll be the field thats listed in the first
column and linked to the entry). Restore the original order of the fields and save your changes again.
One last trick to know about the fields tool: sometimes you need to see the configuration options for more than one field at
a time. Try holding the Shift button while clicking on tabs. This allows you to select multiple fields, and when more than
one field is selected, the configuration panels will stack on the side. This can come in handy when you want to quickly
compare fields.
Figure 5-8
[f0508.png]
Simple, but not at all elegant or user-friendly. Thankfully, Symphony allows you to define how these form elements are
organized and arranged, meaning you actually have quite a bit of control over the content publishing experience.
Let's go back to our Blog Posts section so you can see what I mean:
1. Go to Blueprints > Sections
2. Click on Blog Posts in the sections index
You may not have noticed this, but whenever you create a section, a second tab appears in the section editor below the
section name. Click on the Layout tab.
Figure 5-9
[f0509.png]
This is the section layout tool (Figure 5-9). It enables you to define what a section's entry editor will look likenamely, the
Figure 5-10
[f0510.png]
Now, your Categories section is so simple that we dont really need to look at its layout, but lets do some fine-tuning in
the Comments section. Even though comments are going to be submitted from the front end rather than here in the admin
interface, theres no harm in making it tidier.
Im actually going to leave this one to you. Using whatever column layout, fieldsets, and field arrangement you like, go
ahead and reorganize your Comments layout. Take the time to experiment with various groupings and columns and see
how they affect the entry editor for that section.
Once youre happy with what youve done, well move on.
Creating Relationships
[This functionality hasnt yet been implemented. Will need to revisit once development is further along.]
Managing Sections
Guess what? Your blogs content structure is complete! And if I hadnt spent so much time blathering about all the various
concepts and options you encountered, it probably wouldve only taken you five or six minutes from beginning to end!
The nice thing is, once youre more familiar with all these nuances, youll be able to build a websites content structure in
the blink of an eye.
I just want to review a few more helpful tidbits about managing sections before we move on.
There are two ways to delete a section. The first is to go to the section editor and click the red Delete button. The second
is to go to the sections index, click the sections row (itll be highlighted blue when its selected), choose Delete from the
With selected dropdown below the table, and click Apply. (This paradigm actually applies to pretty much everything in
Symphony).
The other thing to know is that everything you can accomplish in the admin interfacecreating, editing, and deleting
sections, adding and configuring fields, defining a sections layoutall of this can also be achieved by directly editing the
section file (though doing so isnt recommended).
Note
All of the configuration data that makes up a section, from its name and its field makeup to the layout of its entries,
is stored in a physical XML file in your workspace (in the /workspace/sections/ folder). Here's a simplified example
the file for our Blog Posts section:
<section>
<name handle="blog-posts">Blog Posts</name>
...
<fields>
<field>
...
<type>textbox</type>
<element-name>title</element-name>
<name>Title</name>
...
</field>
...
</fields>
<layout>
<column>
<size>large</size>
<fieldset>
<name>Content</name>
<field>title</field>
<field>body</field>
</fieldset>
</column>
<column>
<size>small</size>
<fieldset>
<name>Info</name>
<field>publish date</field>
<field>published</field>
</fieldset>
</column>
</layout>
</section>
Having all of this information in a physical file will help you develop more efficiently. For starters, unlike tables in a
database, files can be easily version-controlled. That means teams can develop content structures for their projects
collaboratively, and iteratively, without worrying about stepping on each others toes. It also means that if you spend time
developing a very finely-tuned section for one site, and then you find that you need to manage similar content in another
site, all you need to do is copy the file over.
Synchronizing Sections
Whenever a section file is updated, the system will detect the changes and ask you to sync the section so your database
can be brought up to date. This is an automated and painless process.
[This functionality hasnt yet been fully implemented. Will need to revisit once development is further along.]
Managing Entries
The last thing we need to discuss in this chapter is how to manage entries. Youve already seen how entries are created
and edited. And by now, I hope youre becoming familiar with Symphonys common user interface paradigms (the
indexes, editors, action buttons, and so on). So most of this should be easy to figure out on your own, but Ill just highlight
a few especially helpful things.
Youll probably find yourself needing to sort, browse, and search through entries on a regular basis. The entries index
table for each section is sortable by whatever fields you choose to include in the table, so if you want to sort your Blog
Posts by date, for instance, make sure to check Show column in that fields configuration. By default, entries are sorted
in order of creation, newest to oldest. The tables are paginated, of course, and the number of items per page can be
adjusted in the system configuration (which well discuss in Chapter 9).
Theres also a filtering mechanism that allows you to run more precise searches on a sections entries. [This functionality
hasnt yet been fully implemented. Will need to revisit once development is further along.]
Deleting entries works exactly like deleting sections. You can do so either from the entry editor itself, or from the entries
index (using the With selected dropdown).
This With selected dropdownor bulk actions menucan also offer other options. Certain field types allow their values
to be toggled via this menu, which means that, depending on how youve modeled a section, youll usually have some
options for updating field values in multiple entries at once. To see it in action, first add a few additional test entries to
your Blog Posts section. Once youve got two or three entries:
1. Navigate back to the Blog Posts index (Content > Blog Posts)
2. Click on one or more rows to select those entries
3. Click on the With Selected dropdown
Youll see that the checkbox field allows its value to be toggled here, so you can publish or unpublish lots of Blog Posts at
once. Select box is another field type that allows its value to be set via the bulk actions menu. This functionality is often
very useful in situations where you need to enforce moderation or publishing workflowsfor example, marking entries as
approved or published, or changing their status.
Summary
Weve covered quite a lot in this chapter. We started by introducing you to the practice of content modeling, so that youd
understand what goes into defining a websites content structure. We then reviewed in more detail the elements that
make up Symphonys content layersections, fields, field types, and entries.
Once you were familiar with the basic architecture and concepts, we went about setting up a content structure for your
blog. Along the way, you learned how to work with each of these elements in turn, from basic section creation to
advanced field configuration and entry management.
There always more to learn, of course. Appendix B outlines in painstaking detail everything you need to know about
common field types, and you should study that closely. On top of that, ever more can be found online in the official
documentation (http://symphony-cms.com/learn/). This is a great start, though, and by now you should feel pretty
comfortable working in Symphonys content layer on your own.
Lets move on to the front end.
Chapter 6: Front-end
Whats in This Chapter
About front-end architecture
Understanding Symphonys front end
Working with Symphonys front end
Now that youve got your content modeled, the next step is to begin thinking about your blogs front endyou know, the
part that everyone sees. What interfaces do you want to provide for your visitors? Where will these interfaces live? How
do you want their URLs to be structured?
Front ends come in all kinds of shapes and sizes, from traditional websites that mimic page-based architectures to
applications with modular, responsive interfaces or even specialized setups like APIs. With so many possibilities, itd be
incredibly limiting for a system to predetermine how your front end should be structured.
Thankfully, Symphony doesnt. That task is left entirely up to you. This means, though, that the blog youve been building
doesnt even have a front end yet. (Just like there was no content structure at all until you defined one in Chapter 5). Dont
believe me? Try pointing your browser to it: http://yoursite.com/.
Figure 6-1
[f0601.png]
The error message you see there (Figure 6-1) is thrown because you havent yet created any interfaces, so Symphony
doesnt know how you want it to handle requests. Until there are structures in place defining where and how people
should be able to access your site, Symphony will simply shrug its shoulders like this and say sorry.
The next step in building your blog, then, is to start mapping these structures out, developing what well call a front-end
architecture. Well begin by talking about what front-end architecture looks like and what it entails. Then Ill explain how a
Symphony front end works, and well review all the important concepts you need to know before you get started.
After that, all thats left is to do the work. Youll see that the process of building out a front end is actually pretty simple
once you know what youre doing. By the time we finish this chapter, youll be well on your way to mastering the art of
front-end architecture, and your blog will be beginning to take visible, tangible shape.
To get you oriented, lets start with another quick exercise:
1. Navigate to Blueprints > Views
2. Click the green Create New button
3. Youll see the view editor (Figure 6-2). Enter Home as the title, and / (a forward slash) as the handle. For now, leave
the rest of the fields blank.
4. Click Create View
Figure 6-2 [f0602.png]
Now, if you return to your front end, youll see that the error is gone. By creating this view, youve defined the first point of
interface for your blog, one that sits at the root (/) of your site. The view is just displaying some simple placeholder content
right now (Figure 6-3), because you havent written its template yet (something well take care of in Chapter 8). But its a
start.
Figure 6-3
[f0603.png]
Before we press on, lets take a moment to assess the task at hand.
Figure 6-4
[f0604.png]
Put very simply, each view constitutes a point of interface between a site and its visitors.
What makes views so powerful is that their URLs can have dynamic parts, or parameters. These get passed through to
the resources and the template, meaning everything that a view needs to take care of, from content retrieval to
presentation, can be dynamic and almost infinitely extensible.
Heres a simple example. Lets say youre building an online childrens store. You create a view called Shop, available
at the URL handle shop, and configure it to accept three parameters in its URL: department, age group, and gender. So if
someone were to visit http://yoursite.com/shop/toys/toddlers/girls, all three parameters would be set:
department = toys
age-group = toddlers
gender = girls
A data source attached to this view could fetch products from your catalog using these dynamic values to filter the results.
Assuming your Products section has the appropriate fields, the above URL would return products from the toys
department, in the toddlers age group, targeted for girls.
Imagine the breadth of possible variations:
http://yoursite.com/shop/clothing/
http://yoursite.com/shop/clothing/infants/
http://yoursite.com/shop/books/
http://yoursite.com/shop/books/adolescents/boys
and so on, ad infinitum.
You could use these values in your templates, too, allowing you to adjust your shops theme for different departments,
age groups, or genders.
In short, you could power an entire shop interface with this single view!
As powerful as views are, you neednt be intimidated. Planning your blogs front-end architecture actually isnt all that
daunting a task. Once Ive reviewed a few important concepts, youll see so for yourself.
Views
Views are points of interface for a website. Everything your visitors can do, from browsing content to submitting forms, is
powered by a view. A view can be as simple as a old-fashioned static page, or robust enough to power a dynamic web
application interface.
Views define a websites URL schema. Every view has a URL handle and is able to accept URL parameters. These two
attributes, along with the ability to nest views hierarchically (well discuss this below), mean views give you full control
View Types
There are circumstances in which you want some views to behave differently than others. For this reason, Symphony
allows for different types of views.
View types define special behaviors and handling options. For example, there is a view type that restricts access to
authenticated users, and one that designates a view to handle 404 errors. View types give you an added measure of
control over not only the structure but also the behavior of your front end interfaces. Whats more, view types can be
provided by extensions, making Symphonys front end endlessly flexible.
URL Parameters
URL parameters allow views to accept dynamic values in their URL. These values can then be used by the view (and its
resources and templates) as it orchestrates the systems response.
Note
Views are able to use values passed via a URLs query string as well. This makes it possible to work with optional
values that shouldnt affect a URLs basic structure, for instance:
http://yoursite.com/shop?sort=price&order=asc&limit=50
This URL would set three query string parametersprice, order, and limitwhich could then be used just like a URL
parameter. Rather than having the view define these explicitly, though, they can be tacked on to the URL on an ad-hoc
basis.
View Resources
View resources enable a view to deliver content or process interactions. There are two types of view resources:
Data sources deliver content to a view, either from within the system or from an external source. As weve seen, the
view is a dynamic environment, and data sources can inherit this dynamism (for instance by filtering their results
using a URL parameter).
Events process interactions. Most commonly, they allow data submitted to a view (via a web form, for instance) to be
saved into the system. Commenting and contact forms are good examples of this sort of behavior.
Well discuss data sources and events in greater depth in Chapter 7.
format.
For each interface we plan, well need to answer a handful of questions:
Where will it live?
What content will it need to provide?
Will it need to process any interactions?
What parameters will it need to accept?
In the interest of keeping things simple, your blog will be powered by just three interfaces: a home view, a view for
reading individual posts, and an archive.
We got a head start on the first of these earlier. Your Home view is going to live at the root (/) of your site. Like most blogs
home pages, itll just display a stream of your most recent posts. The wrinkle is that were going to allow it to be filtered by
category. So well add a URL parameter for category.
The Posts view, a dedicated interface for reading individual posts, will have a handle of /posts, and since well need to
fetch each post by its title, should have a single URL parameter for title. Thatll give us nice, friendly URLs like
http://yoursite.com/posts/how-to-become-a-luchador. This view will also need to process comments, something well take
up in the following chapter.
The Archive view will provide an interface for browsing through your blogs history. Itll be located at /archive, and will
fetch posts based on their publish date. That means itll need to accept parameters for year and month (allowing for URLs
like http://yoursite.com/archive/2010 or http://yoursite.com/archive/2011/01).
We could add a few more interfaces, but lets leave it at this for now.
Bear in mind, this is only one of many, many possible front-end architectures we could have whipped up for your blog.
You might already be thinking of ways youd want to improve things, or additional interfaces youd want to offer. But since
our goal here is just to familiarize you with the system and illustrate some important concepts, youll have to be patient for
the time being. You can always go back and adjust things later if you like.
With this plan in place, scaffolding your front end is going to be a walk in the park. Lets get started.
Using the file system to manage views can be efficient, especially when youre doing large-scale restructuring, but you
dont get the same combination of ease-of-use and fine-grained control as you would with the admin interface.
Figure 6-5
[f0605.png]
The view editor, as you can see, is organized into three parts: Essentials, where you identify the view and its type; URL
Settings, where you define the various properties that will determine the views URL(s); and Resources, where you can
attach data sources and events to the view. Lets take a closer look at each field:
Title is a simple, human-readable title for the viewsomething like Home, About, or Browse Products
View Type allows you to select a type for the view. By default the system provides four view types:
Normal views have no special behaviors or conditions associated with them.
Admin views can only be accessed by users who are logged in to the system.
A 403 view (you should only specify one) is used when a visitor requests a forbidden URL.
http://yoursite.com/posts/choosing-a-stripper
You want:
http://yoursite.com/painting-tips/posts/choosing-a-stripper
http://yoursite.com/handle
Any parameters your view accepts can be tacked on to the end of that URL:
http://yoursite.com/handle/parameter1/parameter2
When your view does have a parent, naturally its URL nests beneath that of the parent:
http://yoursite.com/parent-handle/handle
And if the parent accepts parameters, you can nest behind those too:
http://yoursite.com/parent-handle/parent-parameter/handle
If the parent itself has a parent, the same rules apply. Im going to assume that, by now, you can use your powers of
deduction to figure out what those URLs would look like, so lets move on.
Organizing Views
With all of that in mind, lets make that change we talked about above. There are two ways to nest views: using the parent
field in the view editor, or by physically nesting the view directories in the file system. The latter is less flexible (you cant
nest behind a parent views parameters without opening and editing the view configuration), but its useful nonetheless,
so well look briefly at both methods:
1. Using a file browser, or if necessary the command line, browse to the location on your server or computer where you
installed Symphony.
2. Descend down into the workspace/ directory, and then into views/. Youll see directories there for each of the views
youve created.
3. Move the posts/ directory into the home/ directory, so that the directory hierarchy looks like Figure 6-6:
Figure 6-6
[f0606.png]
Thats it. Your Posts view is now nested beneath your Home view. Symphony instantly recognizes the change:
1. Back in the admin interface, navigate to Blueprints > Views
Youll see that the views index now reflects the change you made in the file system, and Posts is nested beneath Home.
Neat, huh?
Figure 6-7
[f0607.png]
But were not finished yet. Remember, the whole point was to nest our Posts view behind the Home views category
parameter, and thats a level of control we can only get using the admin interface:
1. Click Posts
2. The parent dropdown now lists all the views youve created, along with various permutations including their
parameters (Figure 6-7). Select /:category
3. Click Save Changes
Figure 6-8
[f0608.png]
As you can see, the parent dropdown gives you the ability to choose very precisely where you want to nest a view,
whether directly beneath the parent page or beneath one or more of its parameters. When youre building complex
websites or web applications, this kind of flexibility can come in very handy.
Also, the fact that views can be so easily rearranged, updated, and reorganized means that when youre developing with
Symphony its absolutely trivial to experiment with different architectures, tweaking and adjusting until youve got it just
right.
Summary
And with that, youre finished architecting your blogs front end.
As with content modeling, Ive tried to demonstrate here that front-end architecture really isnt all that difficult once you
understand what it entails. If youre a seasoned developer, of course, most of this was elementary to you, but if not, I hope
youre beginning to feel empowered. This is serious web development work youre doing, the sort that many systems try
to hide from their users. Symphony not only hands you the reins, it actually makes the task easy and enjoyable.
In this chapter, we talked about what it means to develop a front-end architecture, and we reviewed how exactly a
Symphony front end works. We then thoroughly dissected views and their various properties and accoutrements. Finally,
we planned a structure for your blogs front end and then built it, fairly quickly and unceremoniously, in just a handful of
steps.
Though we restrained from doing anything too complex, I hope youve gotten a sense of how powerful views really are.
They give you the ability to craft almost any kind of front end you can imagine. Just how this is so might not be entirely
clear yet, but as we pull everything together over the next two chapters, I think youll begin to see for yourself.
Figure 7-1
[f0701.png]
Now Im going to show you something really cool. Navigate to your blogs Home view, but append ?debug to the end of
the URL (so, http://example.com/?debug). Youll see something that looks like Figure 7-2:
Figure 7-2
[f0702.png]
What youre looking at is Symphonys debug devkitan interface, provided by one of Symphonys core extensions, that
allows you to go behind the scenes of any Symphony view (only if youre logged into the system, of course). The debug
devkit will show you a views XML source content, the stylesheets that have been used to transform it, and the result of
that transformation (e.g. HTML). You can also examine the parameters available to the view at runtime. In short, its X-Ray
vision for every view on your siteallowing you to see exactly how it was built and from what pieces. Neat, right?
Dont worry if youre a little overwhelmed by what you see. If youve never looked at code before you might feel like youre
staring at the title sequence from The Matrix. Take courageIm going to teach you all about XML in the next chapter.
Now, do you remember the sample blog posts we created back in Chapter 5? You should see those entries in your
views source XML. Look closely. See them? Congratulations. Your content has made its way to the front end.
Note
The debug devkit has even more tricks up its sleeve, but well save most of those for Chapter 15. Still, it wont hurt
you to poke around a little bit if youre curious. Youll use this tool a whole lot when developing in Symphony
might as well get familiar with it.
Now that youve laid the foundation for this very basic interactiona visitor arrives at your blogs home view and is
provided with a listing of recent postsits time to think a little more thoroughly about how you imagine people using your
blog. Every interaction you plan is going to have its own specific data needs, and in this chapter your job will be to figure
those out, and to meet them.
Figure 7-3
[f0703.png]
Events process various kinds of interactions, and these can be fairly wide-rangingtheyre able to save data to the
system, set or alter contextual information, or perform other kinds of tasks depending on the event type.
Data sources are more specific in scope. They fetch data and deliver it to the view as XML. Pretty straightforward, but
there are many data source types, each responsible for retrieving content from a different kind of source.
What makes data sources and events so important is not just that they handle the flow of data to and from a view but that
they also define the logic that governs it all. They comprise what would commonly be called the sites application
logicthe rules that determine what the system does and when.
For events, this logic comes in the form of event options, which make it possible to adjust an events behaviorfor
instance by specifying conditions for its execution or adding additional actions to be triggered.
Data sources do most of the heavy lifting, though, when it comes to application logic. Data source filtering is the primary
hinge for determining what content is going to be delivered and under which circumstances. Data sources can also
specify conditions for their execution, rules for how their results should be sorted and limited, and various options for how
those results should be output.
The key to designing data flow, then, is understanding how you can use data sources and events to craft meaningful,
intelligent interactions. Lets review the most important concepts:
Data Sources
Data sources fetch, filter, sort, and output content. Each of these tasks is a sort of logic axisa place where you can have
the system make decisions about what it should do.
Data sources can use dynamic environmental variables. You saw this in our URL parameters example in the previous
chapter. The decisions your data sources make while fetching and processing content dont have to be static or rigid.
Their logic can adapt to their environment.
Data sources can have execution conditions. This is yet another logic axis, another decision point, where you can tell a
data source whether or not to execute at all.
Data sources deliver their content to views. After all that, after all these decisions wrapped in decisions that depend on
other decisions, its still entirely up to the views template to decide what its going to do with the content it gets.
Data source types determine how content can be filtered. Entry data sources, for instance, give you granular filtering and
sorting options on a per-field basis. Dynamic XML data sources, on the other hand, allow you to filter their content using
XPath (more about that in Chapter 8). This means that the logic implicit in the filtering process is both extensible and
context-specificits tailored to the data itself.
Events
Events enable views to take action with their data. For this reason, theyre often seen as complementary to data sources.
Events can do anything from authenticate users to process credit card transactions or run commands on a server. But by
far the most commonly used type of Symphony event is the entry-saving event, which allows system content to be
submitted and saved from the front end.
Note
Entry-saving events are often used to power simple user interactions like commenting, voting, and rating, but they
can just as easily allow you to build fairly complex web applications. The Symphony website (http://symphonycms.com), for example, has user-driven forums and a downloads repository, all powered by simple entry-saving
events.
Event Options
Event options allow you to adjust an events behavior or handling. There are generally three types of event options:
conditions for the events execution (restricting events to authenticated users, for example, or performing anti-spam
tests)
additional actions to be performed (for instance, sending an email when an event is successful)
event-specific settings (such as whether to allow an entry-saving event to process multiple entries in a single
request)
Event options give you an additional vector of control when youre crafting interactions.
Figure 7-4
[f0704.png]
There are five data source types included by default with Symphony (many more are available as extensions). Each is
identified by where it gets its content:
An Entries data source fetches entry content from the sections youve defined in Symphony.
A Users data source fetches user account data from within the system.
A Views data source fetches data about the systems views (useful for building a navigation, for example).
A Dynamic XML data source fetches raw XML from an external source such as an RSS or Atom feed or a web
service or API.
A Static XML data source actually stores raw XML itself and returns that.
Entries is far and away the most common and so is selected by default. All of the data sources well create in this
chapter are going to be Entries data sources. Feel free to cycle through the other types to get a sense of what they look
like, but in this chapter well only cover the Entries type. Youll be introduced to each of the others later in the book, and
Appendix C provides a complete breakdown of all the types and the configuration options available for each.
Lets walk through the configuration options available when creating an Entries data source. There are six sections
Essentials, Conditions, Filtering, Sorting, Limiting, and Output Options.
Essentials
Name is how your data source will be identified within the system.
Section is the section from which your entries will be fetched.
Note / Best Practice
Because data sources are attached to views, and because in very simple websites there can often be a one-to-one
correspondence between a view and the data source that delivers its content, it can be easy to fall into the habit of
thinking about a data source in terms of the view for which youve intended it. For example, you might be tempted
to create a Home view and an accompanying Home data source.
This isnt a great practice, though. Not only will most of your views rely on more than one data source, but youll
also find ways to reuse data sources across multiple views.
Instead, try thinking aboutand namingyour data sources in terms of their logic and the results they yield, rather
than the views youre attaching them to. Youll notice, for instance, in the example at the beginning of this chapter
we named the data source for your Home view Recent Posts rather than something like Home or Homepage
Posts. If we ever decide to create a web feed, and we want to provide it with our most recent posts, weve got a
data source clearly earmarked for just that purpose.
This practice will help you think more carefully about planning your data sources to be flexible and reusable, and in
large projects youll always be able to tell exactly what each data source does just by glancing at its name.
Conditions
The conditions tool (Figure 7-5) allows you to add and configure execution conditions for your data source.
Figure 7-5
[f0705.png]
Each condition you add allows you to specify a parameter to test and a state (is set or is empty), and the data source
will not execute if any of its conditions are met. Data source conditions can help you optimize your views by preventing
unnecessary processing.
Filtering
The filtering tool (Figure 7-6) allows you to add and configure filters to hone your results.
Figure 7-6
[f0706.png]
For each filter you add, you need to specify a field to use. Once youve selected a field, youre presented with a dropdown
of the filtering modes that field offers (a text field, for example, has modes like matches, contains, does not contain,
and so on), and an input for the expression you want to use to filter the results.
Well discuss filteringmodes, patterns, syntaxes, and the likein greater detail below.
Sorting
Sort By allows you to select the field to use for sorting your results. Different field types may have different sorting
rules, so be sure to review the list of field types and their behaviors in Appendix A.
Sort Order allows you to specify how entries will be ordered: ascending, descending, or random. Limiting
Results per page is the number of entries you want the data source to return for each page of results
Page is the page to return, and the field can accept a URL parameter. This allows you to automatically paginate
results simply by using URLs like http://example.com/1/ and http://example.com/2/.
The Redirect to 404 checkbox allows you to have your system respond with a Page not found error when no results
have been returned. Output Options
Included fields allows you to specify which fields content you want to output and, for some fields, the output mode
(some field types allow you to output either formatted or unformatted text, for instance). You can also choose to
include system fields.
Grouping allows you to optionally choose a field to use for grouping entries. Most field types will just group entries
that have the same value, but some have special grouping rules. Date fields, for example, create a grouping
hierarchy by year, month, and then date. This will be helpful for your archive view, where we want to list entries by
month.
Two additional checkboxes allow you to specify whether you want to output Pagination data and Sorting data for
your results alongside the field content.
Having reviewed all the options available, lets go ahead and create another data sourcethe one thatll return your
individual posts. You should already be looking at a blank data source editor:
1. Make sure Entries is selected as the Type
Your Post view will now get live entry data when a valid, published post is requested. Go see for yourself. In Chapter 5,
we created a test post titled My First Post, and we placed it in the Journal category. If you visit
http://example.com/journal/my-first-post/?debug, in the XML source you should see the output of your new data source.
Itll look something like this:
<individual-post>
<entry id=1>
<title handle=my-first-post>My First Post</title>
</entry>
</individual-post>
Filter Mode
Value Expression
Distance
is within
1 mile
Cost of lunch
is less than
$10
Quality of food
is
yummy
Kitchen
Filter Modes
In Chapter 5, I made a big fuss about how important field types are because they enable you to treat distinct kinds of data
differently. This is one of the places where you see this principle in action.
Each field type defines its own filter modes. Text fields, for instance, have modes like contains and regexp (a regular
expression search). Date fields have modes like earlier than or later than. A map location field would have some sort
of radius filtering mode.
What each mode does is pretty straightforward, and I dont imagine youll have much trouble figuring out how they work. If
you do have any questions, though, Appendix A lists each of the core field types and the filtering modes it supports.
Value Expressions
While choosing the field and mode for your filter usually takes all of about four seconds, value expressions can be a bit
more challenging. They dont have to be, though. Theyre evaluated using some relatively simple rules, and once you
understand those, you should have no trouble at all creating data source filters for every purpose. Heres what you need
to know:
By default, expressions are interpreted literally. That means if you enter the word melonhead as a filters value
expression, its going to test the filtering field in each entry for that exact word.
Anything wrapped in curly braces will be evaluated by the system first. As Ive mentioned several times, filters have
access to all of the views environmental variables (URL parameters, contextual information, and so on). In order to
include dynamic values like these in your expression, they must appear inside curly braces so the system knows to
evaluate them and not use them literally.
Within curly braces, the following rules are used when evaluating expressions:
A dollar sign delimits a parameter. So: {$title} or {$category}.
A colon delimits a fallback option. Entering {$category:programming} is akin to saying, If the category parameter is
set, use that, otherwise, use the word programming.
Commas are used as a union operator. They delimit possible matching values that are joined using OR. Entering
programming,football,botany tells the system, Im looking for matches to any of these terms, doesnt matter which one.
Plus signs are used as an intersection operator. They delimit items in a set of required matching values joined by AND.
So entering food+travel says Im looking for matches where the target field contains both of these values.
As Ive noted elsewhere, its the field types that are ultimately responsible for taking care of the filtering, and theyll often
provide additional keywords and operators. One example is the range operater to in date and number fields, allowing
you to enter, say, 1 to 10 or 2009-01-01 to 2009-12-31. Consult Appendix A for a breakdown of all core field types and
the operators and keywords they support.
Note
The combination of the curly braces syntax with all the various delimiters and operators can make for all sorts of
possibilities.
The operators, for example, can come from within the dynamic values themselves. Example: youll recall that your blogs
Home view accepts a category parameter. Lets say you visited http://example.com/writing,reading/. This would set the
value of the category parameter to writing,reading. Which means using {$category} in your filter expression would be
functionally equivalent to using writing,reading.
On the other hand, you could just as easily do something like painting, {$category}. It all depends on your exact use case.
And this applies to field-specific operators too. Its not uncommon to see expressions like 2011-01-01 to {$today}.
As you see, curly braces and delimiters can also be interspersed with literal text: my-favorite-{$color:black}-websites.
Conditional Filtering
If a filter value expression contains only a parameter, and that parameter isnt set when the data source is executed, the
filter rule will be completely ignored and the data source will execute as if the filter didnt exist.
Confused? Hopefully an example will help.
Remember the Recent Posts data source that you created at the beginning of this chapter? The plan for your Home view
was that itd be filterable using a URL parameter called category. You wanted visitors to be able to view all posts at
http://example.com, but then drill down to categories like http://example.com/journal/ or http://example.com/painting/.
Because the sorting and pagination logic is that same, itd be nice to be able to use one data source for all of these
interfaces.
Because of conditional filtering, we can add the category filter to your Recent Posts data source, and if category is not set,
itll just be ignored:
1. Go to Blueprints > Data Sources and click on the Recent Posts data source you created earlier.
2. In the filtering tool, click Add Filter
3. Click the button for the Category field
4. Leave Is selected in the Mode dropdown and enter {$category} in the Value field.
5. Click Save Changes
This allows you to create an additional layer of conditionality without having to duplicate any structure or logic. If the
parameter is set, the filter will be applied. If not, itll be ignored. One data source, as many interfaces as you have
categories.
Lets finish our discussion of filtering by creating another of your blogs data sources, this one for its archive functionality:
1. Go to Blueprints > Data Sources and click Create New
2. Name your data source Posts by Date
3. In the section dropdown, choose Blog Posts
4. In the filtering tool, click Add Filter
5. In the drawer that appears, click the button for the Published field.
6. In the filter panel, select Is in the Mode dropdown and enter yes in the Value field (or click the yes link beneath the
input).
7. Click Add Filter again.
8. In the drawer that appears, click the button for the Publish Date field.
9. In the filter panel, select Is in the Mode dropdown and enter {$year:$this-year}-{$month}
10. In Sort By, select Publish Date and in Sort Order select descending
11. In the Output Options section, in the Group By dropdown, select Publish Date. This will group the result entries first
by year, then month, and then date.
12. [[Attach to view]]
13. Click Create Data Source
This data source uses a date field to filter entries based on the value of two URL parameters: year and month. Year
defaults to the current, meaning if the value is not specified in the URL (i.e. a visitor simply goes to
http://example.com/archive/), itll show entries for this year. Month, on the other hand, has no fallback. If its not provided,
the data source will simply filter by year alone.
Lets make sure its working. Visit http://example.com/archive/?debug. You should see your sample entries again in the
source XML, only this time youll only see the titles, and theyll be nested further down in the hierarchy, because youve
grouped the results by date.
That leaves us with just one more data source to build.
8. For Sort Order, choose ascending. We want older comments at the bottom.
9. We want to include all comments with the post, so uncheck the Paginate Results box.
10. [[Step to define dependencies??]]
11. [[Attach to view]]
12. Click Create Data Source
Using a piece of output from one data source for filtering in another is called data source chaining. With this technique,
multiple data sources can be linked together, each depending on the results of the one before. This can add a great deal
of dynamism to your interfaces.
Data source chains can be one-to-many in either direction. Several dependent data sources can be chained to the same
primary data source, and a single dependent data source can be filtered using results from multiple primary data sources.
Again, lets go back and check our results. The first thing well need to do is add a test comment. Because weve not set
up commenting on the front end yet, well just do this in the admin interface.
1. Go to Content > Comments
2. Click Create New
3. Enter your name and email address in the appropriate fields, and then enter a comment
4. In the Post field, select My First Post
5. Click Save Entry
Now, check out http://example.com/journal/my-first-post/?debug. You should see your comment listed there in the source
XML.
Now that youve been through the ins and outs of how data sources work, lets move on to discuss events.
Event Options
The next section of the event editor allows you to specify options for the event, which youll recall from earlier allow you to
adjust a particular events behavior with additional actions, conditions, and the like.
The base package of Symphony ships with the following event options:
[[This functionality is not fully implemented or defined]]
Lets assume that you want to receive an email notification whenever someone leaves a comment on your blog. Lets
also assume you want to protect your blog against common cross-site scripting attacks. All you have to do is add these
two options to your event.
1. In the Options multiselect, choose the Send Email option and the XSS Filter option.
Because entry-saving events rely on user submissions from the front end, youll want to take other kinds of precautions
with your data too. Theres no stopping a malicious visitor from manually changing names or values in your form markup
to try to save unwanted or potentially harmful data to your system.
Thankfully, Symphony gives you a way to prevent this. You can specify default values and override values for any field.
Default values will be used if no value is submitted for the field. This allows you to specify a fallback if your users skip a
field. Override values are used no matter what users submit. This allows you to prevent users from forcing in data you
dont want.
For our purposes, were capturing five fields. Three will be provided by the user: Name, Email, and Comment. The other
two, Date and Post, well specify as overrides. This will keep malicious users from trying to manually specify values that
they shouldnt:
1. In the Overrides and defaults tool, click Add Item.
2. In the Type dropdown, select Override
3. In the Field dropdown, select Date
4. In the Value field, enter {/data/context/date}
5. Click Add Item again
6. In the Field dropdown, select Post
7. In the Value field, enter {/data/individual-post/entry/@id}
8. [[Step to attach event to view]]
9. Click Create Event
Now, no matter what data is submitted, every comments Date field will be populated with the current date, and the Post
field will be populated with the ID of the post being viewed.
Form Markup
Once you save your event, youll be provided with sample form HTML. You could simply copy and paste this into your
template, but you should know the basic syntax thats at work here. Entry-saving events rely on fields in the POST data
following a naming convention: fields[field-name]. Heres an example:
You can use whatever kinds of form elements you like. The only other requirement is that the name of the input used to
submit the event contains the events handle: action[event-handle]. In your case, then:
Well leave it at that for now. Youll finish setting this up in the next chapter.
Summary
In this chapter you were introduced to the concept of data flowthe transactions and exchanges between websites and
their users that make interactions possible on the web. We talked about data flow being defined by infrastructures and by
logic, and you learned that, in Symphony, designing data flows means:
identifying the data needs of each of your interfaces
building the infrastructure to manage that data
designing the logic that will make it all work
You were then introduced to the two elements that regulate data flow in a Symphony websitedata sources and events.
You learned ins and outs of each, and you went on to build out the infrastructure that will be responsible for managing the
flow of data for your blog.
You were also introduced, briefly, to Symphonys debug devkit, which allowed you to check your work and verify that your
content is indeed making its way to the front end.
It is, and that means that your crash course is almost complete. You started by learning how to model content in
Symphony, then how to define front end architecture. Now youve learned how to set these structures in motion and
channel data to and from your interfaces.
Theres just one big piece left to the puzzle: what your visitors will actually see.
Chapter 8: Templating
Whats in This Chapter
Understanding Templating in Symphony
An Introduction to XSLT
Working with View Templates and XSLT Utilities
This is it. Theres only one thing standing between you and your first fully-functioning Symphony website. Your contents
been sculpted. Your front end is in place and is fielding requests. Data is flowing. All that remains is to give your blog a
face, to turn it into something that people can actually use.
In this chapter, youll learn how to template a Symphony websitein other words, how to define the output that will be
returned to your visitors. Most often, youll be outputting HTML pages, but not always. You can also output Atom feeds,
JSON documents, raw XML, or pretty much any other text-based format you can imagine. For the sake of your modest
blog project, though, well stick to plain old XHTML (XML-flavored HTML), at least for now.
This chapters going to be a little more challenging than the previous few. Although Symphonys templating layer is
structurally very simple, conceptually its different than systems you may have encountered elsewhere. On top of that, its
powered by XSLT, which is a language unto itself (and one you may know nothing about). But just because its going to
be challenging doesnt mean it cant be fun. In fact, if I do my job well, youll leave this chapter excited about XSLT and
eager to learn more.
Well start by talking about that conceptual difference, then, in order to explain the unique approach that Symphony takes
to templating. After that, Ill outline the components involved in Symphonys templating layer (which should be easy
there are only two), and then well dive right into XSLT itself. Thats a book-length topic in its own right, but Id like to teach
you enough that you feel comfortable following along with the remainder of this book. A lot of Symphonys punch comes
straight from this wonderful templating language. Once weve gotten through all that, well finish up by writing the
templates that will give your new blog a face, even if its a fairly plain one.
Note
Until now, Ive tried to avoid making too many assumptions about how much web development experience you
have. This is the exception. I need to be able to trust that you know at least the basics of HTML. If you dont, I worry
that this chapter might be a bit overwhelming for you.
If youre not confident in your HTML knowledge or think you could use a refresher (or if youve never even heard of HTML
and at first glance figured it was a leftist political party in Honduras), then its probably a good idea to set this book aside
for a day and read through a quick introduction to HTML. The folks at
http://htmldog.com
Beginner tutorial.
Before we get started exploring Symphonys templating layer, though, lets try a sample exercise to get your feet wet.
1. Go to Framework > Views
2. Click "Home" to edit your Home view
3. Youll see two tabs in the view editor, "Configuration" and "Template" (Figure 8-1)
Figure 8-1
[f0801.png]
4. Click "Template"
The view template editor is fairly simple (Figure 8-2). It contains a large textarea for your template code, and a list of
available XSLT utilities (more on those later).
Figure 8-2
[f0802.png]
By default, Symphony generates a simple starter template for each new viewjust a placeholder that outputs an
XHTML page with some basic info about the view and its data. Dont panic if any of the code scares you. By the end
of this chapter, youll be comfortable with all of it.
The starter template looks like this:
On the whole the syntax should feel vaguely familiar, and if youve got a keen eye youll notice some HTML in there.
For now, were just going to make some very simple changes to this template so it will output the entry titles being
returned by your Recent Posts data source.
5. Just below the line containing
<h1><xsl:value-of select="data/context/view/title"/></h1>
, enter:
<h2>Recent Posts</h2>
<ul>
<xsl:apply-templates select="recent-posts/entry"/>
</ul>
Translation
"Output a second-level header ( h2 ) element containing the text Recent Posts, followed by an unordered list
( ul ) element. Inside the unordered list, I want you to apply templates to the entry items being returned by my
Recent Posts data source."
6. Now, after
</xsl:template>
and before
</xsl:stylesheet>
, enter:
<xsl:template match="recent-posts/entry">
<li>
<xsl:value-of select="title"/>
</li>
</xsl:template>
Translation
"Heres the template I want you to use for those entry items. Just create a list item ( li ) element and inside it
output the entrys title."
Your final template should look like this (Ive emphasized the bits I asked you to add):
Figure 8-3
[f0803.png]
Its pretty barebones at the moment, Ill admit, but its something. The content that you modeled and created yourself back
in Chapter 5 has finally found its way to your adoring public.
Now, if youve never seen XML or XSLT before, that exercise might have been a little intimidating. Dont worry. Like me,
its actually far simpler than it looks. Before we get into figuring out how to crack all that code, though, lets review exactly
how templating works in Symphony.
What is Templating?
Loosely speaking, templating is how a web application prepares the output that it will render to its users. There are lots of
different kinds of web templating systems out there, each with its own virtues (and shortcomings), but the majority of them
can probably be said to take one of two approaches:
The first, which we'll call "parsed output," allows you to write your output directly (in HTML template files, for
instance), adding in dynamic bits via specialized tags or bits of procedural code. The system then parses the
template, evaluates the dynamic bits, and outputs the result.
The other approach, which we'll call "programmed output," allows you to write code that will generate the output
you're after using the system's native programming language.
Of course, this is an oversimplification, and there are certainly exceptions, but in my experience these do seem to be the
dominant paradigms. If you've done any web development before, chances are you're familiar with one or both of them.
The parsed output approach has the benefit of being fairly simple and easier for beginners to grasp. If you already know
how to write HTML, for example, you can can just whip up your templates as normal and then drop in a few copied-andpasted tags where necessary.
The programmed output approach, on the other hand, is very powerful, because you can lean on the full capabilities of a
robust programming language like PHP, Python, or Ruby. If you know the language well, you can do pretty much
anything you want in the course of generating your output.
Both can and have been used to great effect, but they usually have significant drawbacks too. Parsed output, for example,
tends to be very limited, both in terms of the data you can access and what youre able to do with it. These systems often
rely on a narrowly-defined custom syntax or set of functions thats fairly shallow and not useful in other contexts.
Programmed output, on the other hand, has a pretty high barrier of entry for designers and other non-programmers. More
importantly, though, it subjects you to the procedural constraints of languages that arent really designed for templating.
These kinds of systems can easily get messy because often there is no clear distinction between the presentation logic
and, well, everything else.
Whichever approach they take, the vast majority of web templating systems make it difficult or impossible to intelligently
organize and reuse code, and they nearly always leave their dirty little fingerprints all over your output. As a result, in
many systems, templating on the whole can often feel like an afterthoughtsomething pieced together and tacked onto a
system just to allow its content to be turned into HTML and decorated.
Symphonys approach doesnt really fall on this spectrum. Its a radically different tack, one you might call "transformed
output." With it, you craft a standalone system of stylesheets with rules for turning the raw data delivered by the system
into some sort of digestible format. So rather than having you write output laced with procedural code, or procedural code
laced with output, Symphony's templating system is an entirely self-contained layer, powered by a language that was
designed just for templating (XSLT).
This can be a little disorienting if you're accustomed to other kinds of systems, and it isn't without its own drawbacks. For
starters, XSLT can involve a bigger learning curve than simple tag-based template syntaxes, and it's more verbose
(although some people like that about it). There are also things that XSLT can't do as easily as a full-fledged
programming language can.
That said, though, the benefits of a transformed output approach far outweigh these minor gripes. First of all, you have
complete, unfettered access to all the raw data you need to craft your presentation. Also, as I said above, the templating
layer is completely self-contained, which means its clean and lean, and the system cant interfere with your output in any
way. This self-containment also means that your code can be organized elegantly and reused. Finally, and perhaps most
importantly, you get all the benefits of a dedicated, open templating language in XSLT. Well talk about what those
benefits are in a moment.
So what does Symphonys implementation of this approach look like?
Figure 8-4
[f0804.png]
Both view templates and XSLT utilities are simply vanilla XSLT stylesheets. No custom syntax or special processing
required. So in order to understand how Symphonys templating system works, you just need to understand how XSLT
works.
To help you get there, I'm going to whisk you through a basic introduction to XSLT at neck-breaking speed. I hope youre
wearing a helmet. (Not because you need protection, though. Its just funny to imagine you reading this book with a
helmet on.)
Ok, ready?
Understanding XSLT
XSLT is the keystone in a trio of languages developed to transform and format XML. Collectively, those languages are
known as XSL, or Extensible Stylesheet Language.
Each member of the XSL family has a specific role:
XSLT, or XSL Transformations, is used to transform XML data into other kinds of output.
XPath, or XML Path Language, is used to identify nodes in an XML document for transformation or formatting.
XSL-FO, or XSL Formatting Objects, is a presentational language used for formatting XML data, usually for print.
In the Symphony context, we only need to talk about the first two. XSL-FO can be useful for things like PDF-generation,
but that sort of thing is a bit advanced for this book.
Though the usage of XSLT as a web templating language is not exactly commonplace, there are lots of factors that make
it ideal for this exact purpose. Heres a handful of them:
Its an XML technology. This means native handling of every web feed, every XHTML page, every RDF format, and
nearly every API that exists on the web.
Its an open standard. Maintained by the worlds web standards body (W3C), XSLT is widely-used, widelysupported, and well-documented. You wont have trouble finding resources or getting answers, and once youve
learned XSLT it can be helpful anywhere XML is used (which is pretty much everywhere).
Its content-driven. Everything you output is directly tied to the data you need to present, meaning your presentation
can always be lean and semantic.
Its rule-based. Rules are much more powerful than mixtures of markup and procedural code. They are distinct and
self-contained, but can also have complex relationships and interdependencies.
Its flexible. XSLT can output nearly any text-based format there is, even ones that havent been invented yet.
Its a complete templating language. With XSLT you can craft an organized, coherent presentation system rather
than cobbling pages together out of snippets and tags using languages like PHP.
In short, XSLT is what one might call "awesomecake," and after reading about all the ways it can make your life easier,
theres a good chance youre standing up doing fist pumps right now. With your helmet on. Which is fantastic.
So heres how it all works...
XSLT defines sets of instructions that are used to transform source XML and create some kind of output (Figure 8-5).
Figure 8-5
[f0805.png]
Lets look at a few very simplistic examples of this process to give you an idea of what I mean. Just try to follow along as
best you can, but dont panic if anything confuses youwell go through it all in more detail below.
Imagine that you have the following XML content:
<book>
<title>Symphony Start to Finish</title>
<author>Craig Zheng</author>
</book>
Well assume you dont need to do anything fancy with ityou just want to output the books title. In your XSLT stylesheet,
the first thing youd do is write a template rule that matches that book element:
<xsl:template match="book">
do stuff
</xsl:template>
Now anything you put inside this template will be used to generate output when that element gets processed. Since you
just want to spit out the books title, youd write:
<xsl:template match="book">
<xsl:value-of select="title"/>
</xsl:template>
That template, applied to the XML above, would just output the text from the title element:
And if you wanted to output XML or HTML, you would do something like this:
<xsl:template match="book">
<h1><xsl:value-of select="title"/></h1>
</xsl:template>
Not too bad so far, right? Before we get into the nitty gritty details of the language, lets step back and review whats
actually going on during an XSLT transformation.
Parsing XML
The first thing the processor does during a transformation is load the source XML. It needs to parse all of the data into a
document treea hierarchy of identifiable bits called nodesso that the stylesheet can work with it. Lets look at how
XML data is broken down.
Note
Well stick to the basics hereif you want a detailed history of the language or a thorough breakdown, there are
much better places to get it than this. Were just going to concern ourselves with what you need to know in order to
grasp the fundamentals of XSLT.
XML is a markup language, which basically means that you use it to describe content in some way. For example, look at
this text:
Amazon
That could be any of a half-dozen thingsthe internet company, the rainforest, the mythical tribe of female warriors. So
lets use XML to mark it up:
<river>Amazon</river>
Ok, now the text has got some meaning attached to it. Youre no longer just looking at some ambiguous word but at a
meaningful XML element.
At its very simplest, XML is made up of elements like thisjust various things that exist in the universe of a particular XML
document. A menu, for example, might have elements like dish and beverage, while a real estate listing might have
elements like house or apartment.
Elements are identified by tags. In the example above, and are the tags. One opens the element, the other closes it
anything in between is the elements content. Elements can have textual content, as above, or can contain child
elements, like this:
<river>
<name>Amazon</name>
</river>
If an element hasnt got any content at all, the opening tag can simply close itself:
<river />
Elements can also have attributeskey-value pairs that store additional information for the element:
Taken all together, the basic ingredients of XML syntax are pretty straightforward:
Each of themelements, attributes, and textis a different kind of node that can be identified and processed during an
XSLT transformation.
Now, if youve ever written any HTML in your life, all of this should look pretty familiar. If not, Im fairly certain you wont
have any trouble catching on. After all, the syntax, by definition, is descriptive. Lets imagine what a house might look like,
for example, if we described it with XML:
Not too difficult, right? Weve got a house element with a few descriptive attributes and a couple of room elements for
children.
Now lets look at a snippet of the XML that your Recent Posts data source is providing to your Home view:
<recent-posts>
<entry id="2">
<title handle="my-second-post">My Second Post</title>
<category handle="journal">Journal</category>
<publish-date>2011-01-21</publish-date>
</entry>
<entry id="1">
<title handle="my-first-post">My First Post</title>
<category handle="journal">Journal</category>
<publish-date>2011-01-19</publish-date>
</entry>
</recent-posts>
If you can parse the above and identify the two entries and the various nodes that comprise them, then congratulations...
youre already conversant in XML! (You must have a really fantastic teacher.) And youll be glad to know that XSLT is
itself an XML format, which means you already have a basic understanding of its syntax!
Note
This is all simplified, of course. There are lots of little rules and wrinkles that youll have to learn. For instance, XML
is a very strict language and most use cases require it to be well-formedmeaning elements must be nested
properly, closed properly, contain only valid characters, and so on. But well cover most of those rules as we go
along. No need to get bogged down right now.
So, as I was saying above, once the XSLT processor loads an XML source document, it begins stepping through its
nodes, one by one. Lets look at the XML for your Home view to see how this works. You can see the source for yourself
at
http://example.com/?debug
<data>
<context>
<view>
<title>Home</title>
<handle>home</handle>
<path>/</path>
<current-url>http://example.com/</current-url>
</view>
<system>
<site-name>Tales of a Highway Bandit Hacker</site-name>
<site-url>http://example.com</site-url>
<admin-url> http://example.com/symphony</admin-url>
<symphony-version>3.0</symphony-version>
</system>
<date>
<today>2011-01-25</today>
<current-time>19:03</current-time>
<this-year>2011</this-year>
<this-month>01</this-month>
<this-day>25</this-day>
<timezone>America/New_York</timezone>
</date>
...
</context>
<recent-posts section="blog-posts">
<entry id="2">
<title mode="formatted" handle="my-second-entry">My Second entry</title>
<body mode="formatted">is flavored like potato.</body>
<publish-date time="15:38" weekday="6">2011-02-12</publish-date>
<category handle="journal">Journal</category>
</entry>
<entry id="1">
<title mode="formatted" handle="my-first-entry">My First Entry</title>
<body mode="formatted">Is flavored like awesomesauce</body>
<publish-date time="15:38" weekday="3">2011-01-12</publish-date>
<category handle="journal">Journal</category>
</entry>
</recent-posts>
</data>
The processor starts at the root (or document) node, which is a node that contains the entire source tree. It then
processes the top-most element (in this case,
data
), and begins working through its children one by one. First up would
be the context elementthe processor would crawl down through each of its descendants ( view ,
system
site-name
data
title
handle
path
Templates
Templates are where all of the action happens, as you saw in some of the simple examples above. They are the real
meat of an XSLT stylesheet, and they define most of what happens during a transformationbuilding output, specifying
logic, routing the processor, and so on.
There are two types of templates, template rules (sometimes called "matching templates") and named templates. Both are
defined using
xsl:template
elements. The stylesheet youre using to transform the XML above has two templates in it:
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="data/context/website/name"/></title>
</head>
<body>
<h1><xsl:value-of select="data/context/view/title"/></h1>
<h2>Recent Posts</h2>
<ul>
<xsl:apply-templates select="data/recent-posts/entry"/>
</ul>
</body>
</html>
</xsl:template>
<xsl:template match="recent-posts/entry">
<li>
<xsl:value-of select="title"/>
</li>
</xsl:template>
Both of these are template rulesthey specify the nodes to which they should be applied using a pattern in their match
attribute (more on those patterns in a moment). When the processor reaches nodes that match the pattern, it follows the
instructions provided by the template. Template rules can have more than one match pattern (theyre separated by the
pipe character, | ), meaning the same template can be used to process different node-sets.
The other kind of template, the named template, isnt matched to the source tree but rather is invoked explicitly. Well
discuss these more in depth a bit later.
Note
If youre accustomed to writing CSS rules, which have a selector and then a set of declarations, template rules are
sort of an analogous structure. The match attribute contains the "selector," and then the template contains details
about how the selected node is to be handled:
<xsl:template match="recent-posts/entry">
do stuff
</xsl:template>
Template rules are matched to source nodes using XPath patterns. Lets look at the two that are used in the stylesheet
above:
and
recent-posts/entry
Each of these patterns is used to match the template to a particular node or node-set in the source XML. The first matches
the root node; the second matches entry elements that are children of a recent-posts element.
A great deal of what templates do depends on being able to select or match nodes in the source tree like this, so lets
take a quick detour into the world of XPath so you can get a sense of how these expressions work.
Note
The debug devkit actually allows you to test XPath expressions live on your source XML. If you go to
http://example.com/?debug
//*
you type into that bar will highlight the matching node or nodes in the source XML. Its a tremendously helpful tool
for learning XPath. As we walk through the various kinds of XPath expressions in this section, feel free to test them
out. You can also experiment with expressions of your own to get a sense of what works and what doesnt.
/context/date/today
Easy enough, right? Each bit is the name of an element, and each slash indicates a level in the hierarchy.
Note
When youre describing locations like this, context becomes an important factor.
Patterns are not evaluated relative to any context because theyre just general conditions that nodes need to
match. So something like
match="recent-posts/entry"
match="entry"
will apply to any entry element in the entire source tree, and
will apply to all entry elements that are a child of a recent-posts element.
Expressions in general, though, are evaluated relative to the node being processed. So if you have a template rule
that matches
/context/date
expressions like
entry
, any XPath you use inside that template has to be relative to the date element. Path
and
wouldnt work because those elements dont exist inside the date
recent-posts/entry
element.
When youre dealing with relative paths like this, you have to be able to move around the source tree. XPath makes
this possible with axes (this is an advanced topic, so Ill just give you the highlights and you can read up on your
own). There are 13 axes, among them
parent::
ancestor::
following::
child::entry ). The
descendent::
child::
nodes that are not children or direct descendents of the current context node.
Many axes have shorthand equivalents, so
//entry
is the same as
../context
descendent-or-self::entry
is the same as
parent::context
(itll look for entry elements at any depth from the context node).
Aside from using axes, the other way to sidestep the current nodes context is to make an expression root-relative
by preceding it with a forward slash:
/context
. You can then build your expression to target a node based on its
@id
//entry/@id
There are also times when you dont want to select an entire element, only its text content. In that case, youd use text() to
specifically target the text node:
/context/view/title/text()
/data/recent-posts/entry[@id = 2]
//entry[last()]
The part of the expression that appears in brackets is called a predicate. Predicates allow you to specify additional
conditions for selecting a node. The predicate doesnt always have to come at the end of the expression, either:
/data/recent-posts/entry[@id = 2]/title/@handle
Cool, huh?
Theres a lot more to XPath than thisthe
position()
count()
, and
substring()
but well continue to flesh that stuff out over the rest of the book. This should be enough for now.
If youve done much web development, hopefully XPath syntax feels sort of natural to you. Its actually not unlike many
other selector languages, and the very popular jQuery framework actually supports some XPath syntax itself. If youre
confused, though, you might want to read up a bit on your own before we get into more advanced XSLT techniques in
later chapters.
Anyway, now that youve gotten a rundown of XPath syntax, lets get back to the task at handexplaining the role that
templates play in an XSLT transformation.
<xsl:template match="/">
</xsl:template>
the processor would simply stop there and output nothing at all. It wouldnt step through any of remaining nodes unless
you told it to.
In your Home view template, then, the first template rule matches the root node and stops the processor from going about
its normal business. Then it builds the overall structure for an XHTML page, and explicitly tells the processor where and
how to proceed using the xsl:apply-templates element:
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="data/context/website/name"/></title>
</head>
<body>
<h1><xsl:value-of select="data/context/view/title"/></h1>
<h2>Recent Posts</h2>
<ul>
<xsl:apply-templates select="data/recent-posts/entry"/>
</ul>
</body>
</html>
</xsl:template>
If used without a
select
<xsl:apply-templates/>
merry way, to resume its normal processing flow. In the example above, though, you actually dont want it crawling
through all of the XML; you have a specific template you want it to apply in a very specific place, so you direct it to the
nodes that match that template.
Note
<xsl:apply-templates>
is only one way for a template to direct the processor. You can also iterate over nodes using .
In fact, the stylesheet weve been talking about couldve been written with only one template:
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="data/context/website/name"/></title>
</head>
<body>
<h1><xsl:value-of select="data/context/view/title"/></h1>
<h2>Recent Posts</h2>
<ul>
<xsl:for-each select="data/recent-posts/entry">
<li>
<xsl:value-of select="title"/>
</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
This would produce the same output, but its generally not as flexible. In most cases, its better to handle different kinds of
source content using discrete templates. This way, your code is easier to maintain and reuse (even if the structure of the
source XML changes).
This may seem like a roundabout way to achieve your desired output structure, but the point is that its content-centric and
imminently modular. As you continue to learn and use XSLT, youll come to appreciate how powerful this system can be.
Write Output
As youve seen, templates are also responsible for building the output that will result from a transformation.
One of the most basic things you can do in a template is to specify output directly. If youre building an XML document,
this output can come in the form of literal result elements. All this means is that you actually just put the elements you
want in your output directly into the template. This is what youve done in the example abovethe
<body>
<h1>
<ul>
<html>
<head>
You can also write plain text content or build nodes for your output explicitly using instructions like xsl:element,
xsl:attribute, and xsl:text, but we wont get into that right now since your output is all fairly simple. Youll see these in
action in some of the later chapters.
Get Source Data
Of course, a major reason for using XSLT in the first place is to work with the XML source document, and one of the things
youll need to do most often in your templates is pull data from that source document to add to your output. There are a
few very simple ways to do this.
The first is using the
xsl:value-of
select
attribute
containing an XPath expression which points to a node (or set of nodes) in the source tree. It adds the text value of the
selected node(s) to the output.
The
xsl:copy-of
instruction works almost identically, but instead of adding just the text value, it adds a copy of the node
itself.
Lets use a small snippet from your Home views XML to demonstrate the difference between the two:
<view>
<title>Home</title>
<handle>home</handle>
<path>/</path>
<current-url>http://example.com/</current-url>
</view>
Using
<xsl:value-of select="view/handle"/>
<handle>home</handle>
<xsl:copy-of select="view/handle"/>
would output
Make sense? Now, what happens if you want to include data from your source tree in an attribute of a literal result
element in your output? You certainly cannot write something like:
Thats all kinds of broken, and youd probably bring down the entire internet and wipe out a penguin colony if you tried it.
You could use an xsl:attribute instruction, but that can be a pain for something so simple. Luckily, theres another way to
output source data in this scenario; its called the attribute value template. It allows you, in an attribute of a literal result
element, to wrap an XPath expression in curly braces
{}
. The processor will then evaluate the expression, turn its value
into a string, and add it to the output. So to build a link to the view above, youd just do:
<a href="{view/current-url}">Home</a>
<a href="http://example.com{view/path}">Home</a>
There are other ways to grab source data, and lots things you can do with that data before you output it, but these
fundamentals will suffice for now.
Other Advanced Mumbo-Jumbo
What youve seen so far are the basics, but XSLT and XPath can do much, much more. This is not the time or the place to
try to go through all of the capabilities of each language, but I do want to give you a glimpse of the various kinds of things
Im leaving unsaid, for example:
You can define and use variables and parameters. These can be local or global in scope and are able to store
values or even entire node-sets.
You can also create various kinds of conditional logic (using elements like xsl:if and xsl:choose)
You can define advanced operations for the processor like the sorting of node-sets
You can take advantage of XPaths many functions, which allow you to manipulate strings, perform math operations,
compare values, and more.
For more examples of cool things you can do with XSLT templates, check out http://xsltea.com/.
===
So, to summarize what weve covered up to this point, templates contain instructions for the processor to follow. You can
use templates to structure an output document, define processing logic, write output, grab and manipulate source data,
and much more. They are pretty powerful things.
A lot of their power, though, actually comes not from what they can do but from how they can be organized and applied.
<xsl:import href="path-to-stylesheet.xsl"/>
Or:
<xsl:include href="path-to-stylesheet.xsl"/>
This is how Symphonys XSLT utilities are pulled into a transformation by a view template. The view template can contain
any instructions specific to that view, and everything else can be abstracted into XSLT utilities.
Note
Theres a subtle difference between including and importing, but you dont need to worry about it at the moment.
Were going to discuss the subject in much more detail in Chapters 12 and 14.
Named Templates
As I mentioned earlier, in addition to matching source nodes, templates can also be called explicitly by name. Named
templates are often used for specific tasks that can be helpful in multiple contextsthings like formatting dates, building
lists, truncating strings, and so on.
What makes named templates especially useful is that they can be passed parameters when theyre called. So you could
have a generic template for truncating strings, for instance, and then you could call that template from any context and
have it truncate some bit of text to a desired length:
<xsl:call-template name="truncate-string">
<xsl:with-param name="string" select="path/to/content"/>
<xsl:with-param name="length" select="250"/>
</xsl:call-template>
This allows you to keep the template itself generic enough to be applied to any string, in any context, and invoke it only as
needed.
Note
Calling named templates with parameters is a common way to do recursive operations in XSLT.
Priorities
Because XSLT allows you to build a complex system of template rules and instructions, the system needs a way to
decide what to do when the node its processing is matched by more than one template rule. Theres a lot that goes into
this decision, but the primary method of defining which template will win out is with a
priority
attribute:
The priority attribute can contain any real number, positive or negative. The template with the highest priority will be used.
Modes
Weve already talked quite a bit about the ability to apply the same template to multiple nodes. Sometimes, though, you
need to do the oppositespecify multiple ways or modes of processing the same content.
XSLT makes this possible with a mode attribute. Ill spare you the details for now, but youll see a useful example of
modes in Chapter 12, when we abstract your HTML
<head>
Anatomy of a Stylesheet
So how does this all come together? Lets take another look at your home view template and break it down:
Because every XSLT stylesheet is also an XML document, they all begin with what is called an XML declaration
basically just a line identifying the file as XML. It looks like this:
All XML documents also have whats called a root element. This is a single element that contains all the other elements in
the document. The root element of every XSLT stylesheet is
<xsl:stylesheet>
Note
The xsl: you see in front of the elements name is a namespace prefix. XML namespaces are a pretty advanced
topic, and you dont need to worry too much about them now, but the basic idea is actually quite simple.
Because XML formats are allowed to define whatever elements they like, its possible for the same element names to be
used in different contexts. Namespacing helps avoid confusion between formats, sort of like area codes in U.S. telephone
numbers. Calling within an area code only requires a seven-digit number, but across the country lots and lots of people
share the same seven-digit telephone number. Area codes are prefixes that allow people to communicate across
different areas without confusion.
Everything in an XSLT stylesheet, then, is contained within an element that looks like this:
Note
Youll notice that the root element has two attributes. The first declares the xsl namespace so that the processor
knows how to interpret the elements it finds. The second declares the version of XSLT that youre using.
Top-Level Elements
The elements that can be direct children of xsl:stylesheet are called top-level elements. There arent many of thesejust
a dozen in totalwhich means that XSLT stylesheets are actually pretty simple, structurally speaking.
Youve already seen the
xsl:import
and
xsl:include
elements. If you use those, they need to go before any other top-level
elements. I also mentioned earlier that you could declare global parameters and variables ( xsl:param and
And of course theres
xsl:template
xsl:variable
).
. Aside from those, theres only one more important top-level element to talk about.
Because XSLT can transform XML into any kind of text-based format, you need to be able to configure a transformations
output. You can do this with a series of attributes in a top-level element called
xsl:output
<xsl:output method="xml"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/ xhtml1-strict.dtd"
omit-xml-declaration="yes"
encoding="UTF-8"
indent="yes" />
An XSLT stylesheet can have one of the following three output methods:
html
, or
text
Your home view templates output element begins by setting the output method as
xml
xml
xml
XML formats, html for normal HTML documents, and text for everything else.
XHTML, and adds a couple of doctype attributes for the result document. It then specifies that it wants to omit the XML
declaration that normally sits at the top of an XML document, and that its output should be encoded as UTF-8. Finally, it
opts to have the output nicely indented. For your blog project, all of your view templates will use these same settings.
Most of the remaining top-level elements are seldom-used in a Symphony context, so most of the stylesheets youll create
will have a structure that looks more or less like Figure 8-6:
Figure 8-6
[f0806.png]
Exhale. That concludes your whirlwind tour of XSLT. Hopefully youve begun to see how it can empower you to craft
elegant, modular, content-driven presentation systems. But if youre not impressed yet, just know that it gets a lot cooler
than this. Were barely scratching the surface here. The point of this walkthrough has just been to expose you to XSLTs
syntax and basic structures so that you have a point of reference as we begin reviewing the languages fundamentals.
[[deleted]]
Either way, youve learned enough that we can move on for now. Im sure youre itching to get your blogs front end up
and running, so lets not dally any longer.
<data>
<context>
<view>
<title>Home</title>
<handle>home</handle>
<path>/</path>
<current-url>http://example.com/</current-url>
</view>
<system>
<site-name>Tales of a Highway Bandit Hacker</site-name>
<site-url>http://example.com</site-url>
<admin-url> http://example.com/symphony</admin-url>
<symphony-version>3.0</symphony-version>
</system>
<date>
<today>2011-01-25</today>
<current-time>19:03</current-time>
<this-year>2011</this-year>
<this-month>01</this-month>
<this-day>25</this-day>
<timezone>America/New_York</timezone>
</date>
...
</context>
<recent-posts section="blog-posts">
<entry id="2">
<title mode="formatted" handle="my-second-entry">My Second entry</title>
<body mode="formatted"><p>Something something something complete.</p></body>
<publish-date time="15:38" weekday="6">2011-02-12</publish-date>
<category handle="journal">Journal</category>
</entry>
<entry id="1">
<title mode="formatted" handle="my-first-entry">My First Entry</title>
<body mode="formatted"><p>Something something something dark side.</p></body>
<publish-date time="15:38" weekday="3">2011-01-12</publish-date>
<category handle="journal">Journal</category>
</entry>
</recent-posts>
</data>
Thats all the data thats available to you as youre crafting your output. Now lets think about your desired XHTML:
<html>
<head>
<title>The Name of Your Website</title>
</head>
<body>
<h1>The Name of Your Website</h1>
<ul id="posts">
<li>
<h2><a href="/category/my-second-entry">My Second Entry</a></h2>
<p class="date">2011-02-12</p>
<p>Something something something complete.</p>
</li>
</ul>
</body>
</html>
Pretty simple, and thankfully, the default template has gotten you much of the way there. It sets up a basic XHTML
document, taking care of the output declaration and so on. Heres what it looks like after we tweaked at the beginning of
the chapter:
As you can see, theres not much that you need to do. In the root template (Im going to adopt the convention of referring
to template rules according the nodes they match), youll just replace the content of the
of the "Recent Posts"
1. In the
<h1>
<h2>
, change the
select
attribute of the
value-of
element to
<h1><xsl:value-of select="context/website/name"/></h1>
2. Delete the
<h1>
, and add an id to the posts list. Lets take care of all that now.
<h2>Recent Posts</h2>
<ul>
line
context/website/name
<ul id="posts">
Now the last thing youll need to do is beef up the list items that are being output by the recent posts entry template. Right
now, they just contain title text, but as you can see in the desired output, youre aiming for a linked title heading, a
paragraph containing the date, and then the entrys textual content.
Building the title heading should be fairly easy. The
<h2>
and the
<a>
content, we just need to use value-of to grab the title. The attribute is the only tricky bit. Youll recall that individual posts
will have URLs like posts/category/title. So youll have to piece together the anchors href attribute out of several different
bits:
The websites base URL, which we can get from
The entrys category:
The entrys title:
category/@handle
/context/system/site-url
title/@handle
Youll notice a difference between the first expression and the latter two. Because this template matches
posts/entry
recent-
nodes, were able to grab the category and title data directly, but for the base URL we need to jump outside
Next you want to add a paragraph for the entrys date. This bits pretty easy:
2011-02-05
Finally, you want to output the entrys content. Because were capturing the content using Markdown formatting, itll be
available as HTML, so youll want to use
xsl:copy-of
<xsl:copy-of select="body/node()"/>
Why
body/node()
body ?
If you used
<xsl:copy-of select="body"/>
element in your output too. What you want is a copy of everything inside the
node()
<body>
One last optional bit: if you want some basic styling for your blog, you can add the following stylesheet to your head:
Thatll make your site a bit more presentable for the time being. Heres the final stylesheet:
Got it? Ok, save the template. Now if you visit your home view you should see the full posts being displayed (Figure 8-7).
Dont worry that theres no navigation yet. Well get to that shortly.
Figure 8-7
[f0807.png]
Post View
Now lets get the Post view set up so those title links will actually point to something. To edit the Post view template, either
go to Framework > Views, click "Post," and switch to the template tab, or open
/workspace/views/post/post.xsl
in your text
<html>
<head>
<title>The Name of Your Website</title>
</head>
<body>
<h1>Title of the post</h1>
<p class="date">2012-12-21</p>
<p>All the content...</p>
</body>
</html>
Have a peek at your source XML ( http://example/com/post/journal/my-first-entry?debug ). I wont paste it here, but try to locate
the bits of data youre going to needthe post title, the date, the body content. Use the XPath tester to see if you can
figure out the expressions that will point to them.
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="context/website/name"/></title>
<!-- Optional stylesheet line goes here -->
</head>
<body>
<xsl:apply-templates select="individual-post/entry"/>
</body>
</html>
</xsl:template>
<xsl:template match="individual-post/entry">
<h1><xsl:value-of select="title"/></h1>
<p class="date"><xsl:value-of select="publish-date"/></p>
<xsl:copy-of select="body/node()"/>
</xsl:template>
Copy those two templates into your stylesheet (replacing the old one), and save it. If you go back to your Home view now,
and click on a post title, youll be able to view your post.
Archive View
Last, but not least, lets tackle the Archive view. Go to Framework > Views and click "Archive" and then the template tab,
or open
/workspace/views/archive/archive.xsl
<html>
<head>
<title>The Name of Your Website</title>
</head>
<body id="archive">
<h1>Archive</h1>
<h2>2012</h2>
<h3>December</h3>
<ul>
<li><a href="http://example.com/posts/journal/my-second-entry">My Second Entry</a></li>
</ul>
</body>
</html>
Pretty simple, as usual, but the XML here is going to be a little different. In the last chapter, when you created the Posts by
Date data source, you opted to have the results grouped by date. So instead of just having a set of entry elements, then,
your data source will have a slightly more complex hierarchy that looks something like this:
...
<posts-by-date>
<year value="2012">
<month value="11">
<entry/>
</month>
<month value="12">
<entry/>
</month>
</year>
</posts-by-date>
...
Your Archive view is set up to list entries either from a single month, or from an entire year, grouped by month. So this
data structure plays right into your hands. You can have a template match the month elements, allowing you do render a
separate heading and list for each month. Then another template can take care of the entry elements themselves. Itll look
like this:
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="context/website/name"/></title>
<!-- Optional stylesheet line goes here -->
</head>
<body>
<h1>Archive</h1>
<h2><xsl:value-of select="posts-by-date/year/@value"/></h2>
<xsl:apply-templates select="posts-by-date/year/month"/>
</body>
</html>
</xsl:template>
<xsl:template match="month">
<h3><xsl:value-of select="@value"/></h3>
<ul>
<xsl:apply-templates select="entry"/>
</ul>
</xsl:template>
<xsl:template match="posts-by-date//entry">
<li>
<a href="{/context/website/url}/posts/{category/@handle}/{title/@handle}">
<xsl:value-of select="title"/>
</a>
</li>
</xsl:template>
In the root template, you include two headings, one for the views name and one for the year. Then you apply templates to
the month elements. The template for months includes a third heading (for now containing just the months number), and
an unordered list for its entries. Inside the unordered list, it applies templates to its child entry elements. That third
template, for entries, just outputs a list item and a link for each entry.
Drop those three templates into your archive view stylesheet (replacing the default one), and save it. You should now
have a pretty simple, but functional, archive view.
navigation.xsl
The stylesheet you need is simpleone named template containing the output youre looking for:
Enter this stylesheet into the editor and click "Create XSLT utility."
<xsl:import href="navigation.xsl"/>
<xsl:call-template name="navigation"/>
Once youve updated and saved each of you view templates, youll see that each view on your front end includes a
navigation menu now. That code is shared among all the views.
Of course, theres a lot more they could share, and a lot more we could do to organize your templates more efficiently, but
youll get there. Whats important right now is that youve got a basic sense of how view templates and XSLT utilities can
fit together.
Summary
Lets take a walk down memory lane, all the way back to the beginning of this chapter when you were just sitting there, in
your giant helmet, with no idea what XSLT was or how it worked. Weve come a long way since then, huh?
We talked about Symphonys "transformed output" approach to templating, and about how it differs from the kinds of
templating systems you may have seen in the past. You learned that Symphonys templating layer is comprised of view
templates and XSLT utilities, and powered by XSLT.
After that, you learned what XSLT is and why its a great templating language for the web. You then got a crash course in
XSLT and its accompanying technologies like XML and XPath. You learned about building XPath expressions, writing
XSLT templates, and composing stylesheets.
Finally, you wrote the templates that would make your new blog functional.
As exciting as this is, Im sure youre looking at your blog and thinking, "This is far from finished." Part 3 of the book is
going to help you master all of the most important Symphony workflows, and as you do so youll continue to flesh out and
improve your modest little blog.
Before we move on to all that, though, we need to spend some time discussing issues of system management. How do
you add users? How do you install extensions? Where can you set preferences? Thats what were going to discuss now.
Managing Settings
Settings allow you to configure various aspects of the systems internal behaviorfrom simple display options to things
like file permissions and caching. There are two ways to manage your settings in Symphony: using the admin interface or
by editing the settings files themselves.
The most commonly used settings can be accessed right in the admin interface, at System > Settings (Figure 9-1). Any
settings provided by extensions are made available here as well, in a separate tab.
Figure 9-1
[f0901.png]
PASTE
You can always change any setting by editing these settings files directly, but make sure you know what youre doing. If a
setting requires more than a simple yes/no value, you need to know what will work and what wont.
Lets review the remaining default settings we havent already discussed, so that youll be able to adjust these if
necessary.
Website settings
Version. This will be updated automatically when Symphony is installed or updated. You shouldnt change this or
you might risk throwing off future upgrades.
Email settings
Provided by gateway extensions?
System Settings
Cookie Prefix. Prefix for cookies stored in the browser by Symphony. Defaults to sym- but any string will do.
File Write Mode. Default permissions for files created by Symphony. Defaults to 664 but any mode writable by the
server will work. Dont change this unless you know what youre doing, or you could create a security problem.
Directory Write Mode. Default permissions for directories created by Symphony. Defaults to 775 but any mode
writable by the server will work. Dont change this unless you know what youre doing, or you could create a security
problem.
Archive. Whether system logs should be archived. 1 for yes, 0 for no.
Max Size. Maximum size of the logs archive. When the file reaches this size, old logs will be truncated. Enter a size
in megabytes.
Cache Driver. Method the system will use for caching. Either file or database. [[Whats the difference?]]
Admin Interface
Condense Scripts and Stylesheets. This is an option to have the system condense back-end assets to improve
performance. Accepts yes or no.
Maximum Upload Size. Maximum size for file uploads in the admin interface. Enter a size in megabytes.
Maximum Page Rows. In the admin interfaces index views, the maximum number of items to show per page.
Default is 17.
Default Data Source Type. Default type selected when creating a new data source in the admin interface. Accepts
handle-ized version of any available data source.
Default Event Type. Default type selected when creating a new event in the admin interface. Accepts handle-ized
version of any available event type.
Allow Page subscription. ????
Most of these advanced settings youll never need to touch, but its good to know that they exist and how you can change
them, just in case.
As I said above, extensions can also add their own settings. If they do so, their settings will be available at System >
Settings under the Extensions tab, and in extension settings files in manifest/settings/.
X of Symphonys default extensions provide settings of their own. Lets review those now:
Managing Users
Users are people who can log into your Symphony sites admin interface. When you installed Symphony you created the
systems first user.
Figure 9-2
[f0902.png]
User Roles
Symphonys core allows for only one type of user with full permissions, meaning any user can access anything in the
back end. This is great when youre working on a site by yourself or with a trusted small team because it saves you the
overhead of a complex permissions system.
Once youre dealing with more than a few users, though, its likely that youll need fine-grained control over who has
access to what. Symphonys got your back here too. The system ships with an Access Control Layer (ACL) extension that,
once enabled, allows you to create discrete user roles and specify role-based permissions.
To demonstrate how roles work, lets imagine that youve decided to make your blog a collaborative endeavor. Youve
brought on a second author and
Managing Extensions
Because different people will require different things in different situations, Symphony is designed to allow you to swap
pieces in and out as you need them. This is done via extensions.
A good deal of setting up and managing a Symphony installation, then, is
Managing Extensions
Update notifications
Updating extensions
Note about uninstalling extensions
Summary
Yeah text
But before we dive into all of that, we should begin, naturally, at the beginning. Every web project starts with some degree
of planningwith making decisions about what youre trying to achieve, how things are going to look, how theyll behave,
and so on.
So far in our journey together, Ive been making all these kinds of decisions on your behalf. Youve just followed along
dutifully and trusted me to be right. Thankfully, for your sake, Im every bit as thoughtful and intelligent as I am humble.
Wait
Anyway, sooner or later itll be time for you to build your first real Symphony site on your own, and youre going to need to
be able to scope the project yourself, map it out, manage its development, and so on. And even if youve done this sort of
thing before, it can all look a bit different when you add Symphony to the mix. As with any tool, Symphony will impose a
certain amount of structure, and certain kinds of conditions, on how you go about things. Getting your thinking attuned to
the system early in the process will be an important first step whenever youre about to embark on a new project.
My goal in this chapter, then, is to equip you with tools and techniques that will help you plan Symphony projects
effectively. Well try to keep things brief. I want to talk about three separate planning topicspreparation, project
architecture, and workflowsand for each Ill just quickly review some helpful techniques and pointers.
Whatever your rolehobbyist, independent developer, project managermy hope is that youll leave this chapter feeling
confident in your ability to map out and orchestrate Symphony projects large and small.
Planning to Plan
Blah
Be Open
Every project will be different. Sometimes you know right away how you want a site to look and feel. Other times, its the
content and interactions that are most clear from the outset.
Rather than always forcing yourself to proceed in this or that particular way, try to recognize what it is that youve got in
the beginning and let that drive the planning process.
If what youre starting with is a vision of an interface or a user experience, so be it. You can plan from the outside in, from
sketches and wireframes to front-end architecture and down to the content, letting your vision of the users experience
guide you.
If, on the other hand, the first thing youve got is a well-defined data model, then you can take an inside-out approach,
starting with content outlines and data flow charts and letting those determine the sites structure and design.
Now, of course, if youve already got a tried and true method of scoping and planning projects, by all means feel free to
stick to it if it works for you. But in my experience no one approach is inherently better than any other. It all depends on the
circumstance. And sometimes trying to prematurely force a great content-driven idea into wireframing, or a purely visual
idea into abstract data modeling, can kill momentum and wind up being counter-productive.
Research Extensions
The other reason to become a regular on the Symphony website is that you want to be intimately familiar with the
extensions ecosystem.
As youve seen, Symphony is a lean, lightweight content management framework. All non-essential functionality is
provided by extensions, which means that every project youll build will probably rely heavily on extensions.
These extensions are constantly being developed and refined, and new ones are born every week. You wont be able to
plan your projects effectively without knowing exactly whats out there, what it does, how reliable it is, and so on.
This is especially true of extensions that provide core elements like field types, data source types, and the like. Youve
already seen how important these can be. Field types, for example, determine pretty much every aspect of how your data
can be used. Coming up with a sound content model means knowing what field types are available to you and what the
differences are between them.
Because theres more than one way to do almost everything in the Symphony universe, youll probably spend lots of time
ruminating over various kinds of approaches and implementations when youre getting ready to start a new project.
One of Symphonys best traits is that it makes it very easy for you to try things out quickly and see how they work
(something well discuss at length in the next chapter). But sometimes trial-and-error is too time-consuming, or the scope
of the thing youre trying to figure out is just too broad.
Generally speaking, its a good habit to spend time puzzling through things on your own, researching and weighing
various options and trying to pinpoint the questions and uncertainties. But whenever youre in doubt, do yourself a favor
and ask for help. Youll undoubtedly save yourself lots of time, and probably learn something new in the process.
Make sure your questions are well-considered and specific. Dont be the person who comes to the forum making vague
demands, like Hey tell me how I can implement an ecommerce site. Figure out what exactly your dilemma is. Are you
unsure about your content model? Do you want suggestions for how to set up a certain set of views?
Asking well-thought-out, specific questions will get you clearer, faster answers.
Project Architecture
No particular order...
Products
Label
Field Type
Name
text input
Description
textarea
Image
Category
Configuration Options
/workspace/uploads/products/
Categories::Name
Categories
Label
Field Type
Name
text input
Description
textarea
This is not unlike what you might see in a diagram of a database schema, only simplified, and with some Symphonyspecific bits like upload directories or relationship targets.
As I mentioned above, youll want to pay special attention to the field types at this stage. Theyre the primary determinant
of how youll be able to use your data, and because they also determine how data is stored, changing field types is a
destructive process. So youve got to get it right at the beginning.
I find mapping out a sites content model like this incredibly helpful, but theres a balance to be stricken here. The benefit
of this exercise is to get you thinking in advance about the shape of your content, and to help you see where critical
decision points will be (Should Categories be its own content type? Will I need to be able to attach more than one image
to a Product?). But this outline shouldnt be set in stone, and itll almost certainly change during implementation.
The important thing here is to prioritize completeness over perfection. Dont worry if youre uncertain about a handful of
details, but make sure youve been through the whole content model at least once.
Wireframe
Websites and web applications often begin their lives as wireframessimplified visual outlines of pages or interfaces that
roughly approximate things like layout and content placement (Figure 10-#).
Figure 10-#
Wireframing is a tremendously helpful planning tool and often a great place to start a Symphony project, especially for
non-developers, who might find it difficult to begin with something as abstract as a data model. Wireframes allow you to
start with the part of your project thats probably most tangiblethe interfaces your visitors will see and exploreand
help you get a feel for how your content is going to be used.
Its common to annotate wireframes, normally by placing numbered circles over various parts of the visual and then
adding a corresponding note in the margin. When youre working on a Symphony project, this can be a helpful way to
use what youve got (visual ideas, in this case) to help you begin planning other parts of the system. For example, a
wireframe for a blogs home view might contain annotations like Blog Post entries, 10 most recent and Title, teaser,
date, author (Figure 10-#). Now youve got a head start on a data source and a content type.
Figure 10-#
If youre reading this book, theres a good chance you know all about wireframes and have probably created lots of them
yourself, so Ill leave it at that. If you want to explore the practice a little more in depth, theres a fairly thorough guide at
http://sixrevisions.com/user-interface/website-wireframing/.
Do a Task Analysis
Another technique thats common among information architects and user experience designers is the task analysis or
task flow.
Details can vary, but the basic idea is to chart out what it is that users need to be able to do on your site and where.
Sometimes this takes the form of flow charts that track particular user journeys. Sometimes its a sequential table of user
actions and accompanying system actions. Figure 10-# provides some examples:
Figure 10-#
The important thing is that this sort of exercise gets you thinking about how people will use your site, and that can help
you raise architecture and design questions early on that you might otherwise miss.
If task analysis is part of your planning process, it can be a great place to mine for structural Symphony requirements.
Charting user journeys, for example, can help clarify the interfaces youll need to provide and where theyll live. And
detailing how the system should behave in response to specific user actions is a good way to start planning data sources
and events.
Figure 10-# shows how you might layer Symphony specific details onto the examples provided above.
Figure 10-#
Being able to streamline and organize your presentation layer like this is one of the nicest benefits of using a rule-based
templating system like XSLT, and you should be prepared to take full advantage of it.
Map Everything
Another common technique in web design and development is site mappingpart of the information architecture process
that, in its simplest form, maps a sites pages or interfaces into a hierarchy to help visualize its organization.
With a Symphony project, especially a large or complex one, its often helpful to take this mapping exercise one step
further. You can begin by listing and arranging all of the views you imagine your site will require. Youll want to include
details like their handle and parameters, so that you can get a sense of how your URL schema will look. Views can also
be organized hierarchically, so youll want to capture or represent those relationships too.
Then, for each view, think about what content it needs to display or what interactions it needs to support. This is where
wireframes can come in handy if youve made them. Going through the views this way will give you an overview of the
various kinds of data sources and events youll need, and you can begin to list and describe those too.
What you end up with in the end is a pretty thorough mapping of your front-end. Mine often look like Figure 10-#:
Figure 10-#
This exercise helps you pull disparate pieces together, fill in gaps, and spot redundancies and trouble areas before they
become problems. It can be overkill for small projects, but for large sites, I find it invaluable.
Because I happen to find these techniques so helpful, I created a Project Planning Kit that provides PDF and SVG
templates for creating Symphony-specific wireframes, content outlines, system maps, and the like. The templates have
dozens and dozens of variations and can be printed out or used within your favorite vector drawing program (Figure 10#).
Figure 10-#
You can find the project planning kit in a community-maintained Github repository at http://github.com/####/#####.
Workflows
Of course, getting the system scoped and mapped out is only part of the battle. In addition to knowing what youre going
to build, youll probably want to spend time figuring out how youre going to build it.
This is especially true if youre working with others. When youre working alone, you get to do things however you like. No
one will be stepping on your toes, getting in your way, or making changes while youre not looking. But when youre
working in a team, whether its two people or twenty, things can get complicated very quickly.
In either scenario, it can pay to spend a little bit of time before any project hashing out workflows and procedures to keep
things from getting messy.
Plan to Test
First and foremost, plan to test. The kinds of system specifications you saw above are going to help you spot the easy
errors, like when an interface is misbehaving or is missing content. But youll want to be prepared to catch subtler
problems before your project goes live and they start tripping up your users.
One obvious way to surface these kinds of issues quickly is to develop iterativelybuilding specific sections and
functionalities one-by-one, starting with the simplest implementation and then adding to it little by little and testing
(preferably with real users) all along the way. Well cover this strategy in much more depth in the next chapter.
There are other ways to incorporate testing into your workflows, though, whether its stress-testing your data model with
sample content, seeing how views and data sources respond to unexpected parameters, submitting malformed or
malicious data to your front-end events, and so on. Well talk more about testing and debugging in Chapter 15, but do
yourself a favor and work it into your plans and timelines from the beginning.
Figure 10-#
When youre going to version-control a project, you need to have a plan. Know where youre going to host your
repository. Know how its going to be organized (for example, separate branches for development and deployment code).
And know exactly how you intend to deploy from the repository to the production server.
For individuals and small teams, youll want to keep all of this as simple as possible. But really big projects may require
elaborate schemes for things like branching and versioning, and if youre working with a large team youre going to need
guidelines on how changes should be reviewed and merged. If youre working in an agency setting or planning a big,
ambitious project, make sure you think this stuff through first.
Getting into the details of a version control system like Git are well beyond the scope of this book, but Symphonys online
documentation has loads of details on how to use Git with Symphony, and it will also point you to other helpful Git
resources: http://symphony-cms.com/documentation/git.
[[Symphony 3 may have some built-in db tools, so will have to revisit this]]
Summary
Weve quickly run through a whole bunch of shit that I think you will find helpful next time you have to sit down and plan a
new project.
One technique we havent discussed, though, can often be the most useful of all. Its the anti-plan.
Rapid Prototyping
Interative Development
When everything goes according to plan, it usually involves unicorns and talking fish (because its all in your
imagination).
A whole lot of development methods have gained popularity in the last few decades in response to what is commonly
called Waterfall development. WD is when each phase of planning and development is nicely and neatly completed
and then serves as the basis for the next bit.
As development teams began to realize that this method almost never mapped onto reality, they started coming up with
alternatives: adaptive development, agile development, iterative development... Though each of these has its own
particular definition and history, I think of them as a family of approaches that are trying to solve the same problem in
different ways.
the upshot is that theyre trying to combat the top-heavy process of WD with more flexible approaches where things are
scoped as you go, theres some room for trial ad error, for learning on the go, for prototyping something simple and
building it up... and for all of these tasks, symphonys a great tool its modular, it allows to you build your solution bit by bit,
and so youre able to go in thin layers, or to do a circular thing. when youre building symphony projects these kinds of
approaches can be invaluable, esp when plans are difficult or they fall apart or requirements are shifting. lets give you a
taste of how it works.
Summary
This was fun...
Table of Contents
Introduction
Why You Need Symphony
Symphony in Action
Getting Started
Symphony Anatomy
Content
Front-end
Data Flow
Templating
System Management
Planning Symphony Projects
Adaptive Techniques
1
2
13
22
35
48
64
74
91
119
125
134