Apostrophe 1.5: legacy documentation

Still using Apostrophe 1.5? Check out Apostrophe 2 for your future projects.


Up to the Overview

Download and Installation Guide

There are two ways to get started with Apostrophe. You can start with our sandbox project, which we heartily recommend, or add the apostrophePlugin to your existing Symfony project. The latter only makes sense for experienced Symfony developers whose sites are already well underway. I'll describe both approaches.

But first, let's make sure your webserver meets the requirements for Apostrophe.

System Requirements

Apostrophe requires the following. Note that virtually all of the requirements are included in the asandbox project which you can easily download as a tarball, check out from svn, or copy from svn to your own repository as described below. S

The following must be installed on your system:

  • PHP 5.2.4 or better, with a PDO driver for MySQL (we recommend PHP 5.3.3 or better if possible; the latest in the 5.2.x series is also OK)
  • MySQL 5.0 or better (we will accept patches for greater compatibility with other databases provided they do not damage MySQL support)
  • For the media features: GD support in PHP, and/or the netpbm utilities. netpbm uses much less memory. For best results it's good to have both
  • A few truly excellent hosting companies already have netpbm and ghostscript in place. If you have a Virtual Private Server (and you should, shared hosting is very insecure), you can most likely install netpbm and ghostscript with a few simple commands like sudo apt-get install netpbm and sudo apt-get install ghostscript.

If you are choosing a Linux distribution, we recommend Ubuntu. Ubuntu includes a sufficiently modern version of PHP right out of the box. If you are using Red Hat Enterprise Linux or CentOS, you will need to upgrade PHP to version 5.2.x on your own. This is unfortunate and Red Hat really ought to get a move on and fix it.

A servercheck.php page that verifies these requirements is included in the sandbox. Just visit that page after adding the web folder of the sandbox to your server as the document root of a new site.

Mac users: want to build your site on your own computer first? Please say yes, this is the right way to avoid surprises. You can most easily meet the web server and PHP requirements by installing the latest version of  MAMP. Note that MAMP's PHP must be your command line version of PHP, not Apple's default install of PHP. To fix that, add this line to the .profile file in your home directory:

    export PATH="/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php5/bin:$PATH"

Of course your production server will ultimately need to meet the same requirements with regard to PHP and PDO.

Apple's default version of PHP for Snow Leopard is theoretically capable of working with Apostrophe, but unfortunately Apple chose to ship the very first bleeding-edge version of PHP 5.3 and as of this writing they have not updated it to address the many PHP bugs since discovered and fixed in the PHP 5.3 series.

Yes, you can also use Apostrophe with Microsoft Windows as a hosting environment. Core Apostrophe features do not depend on Unix-specific command line tools and services. We strongly recommend that you use the Microsoft Web Platform PHP accelerator for reasonable performance on Windows.

Ways to Download the Apostrophe Sandbox Project

Download the Tarball or Zip File

The easiest way is to download a tarball or zip archive of the sandbox project.

Now continue with "Apache Configuration" below.

Check It Out From Subversion

Almost as easy and a lot better if you want updates later: just check out the sandbox project with Subversion. You don't have to be an svn expert just to check out the project; one command will do:

    svn co http://svn.apostrophenow.org/sandboxes/asandbox/branches/1.5 asandbox

That will check out the 1.5 stable branch, which is suitable for use with both Symfony 1.3 and Symfony 1.4.

YOU SHOULD USE THE 1.5 STABLE BRANCH. Please do not use the trunk, which is deprecated and will shortly be removed in favor of developing new releases in branches.

Now continue with "Apache Configuration" below.

Copying the Sandbox to Your Own Repository

Checking out the sandbox from svn is a nice way to get started, but you'll soon wonder how to save your own changes when the project is part of our own svn repository. That's why we recommend that you instead copy it to your own repository with  svnforeigncopy each time you want to start a new site. That's what we do. With svnforeigncopy you get a copy of the asandbox project in your own svn repository, with the svn:ignore and svn:externals properties completely intact. You don't get the project history, but since 99% of the code is in the externally referenced plugins and libraries, that's really not a big deal. The important thing is that you are still connected to the latest bug-fix updates for our plugin.

This will give you all of the necessary plugins and the ability to svn update the whole shebang with one command while still being able to commit your changes.

(Note: this technique takes some skill with svn. It's fine to just check out the sandbox project for now.)

Here's an example. In this case I have already copied the svnforeigncopy script to my personal ~/bin folder and made it executable with the chmod command. (That assumes ~/bin is in your PATH, which you can adjust in ~/.profile or ~/.bashrc`.

NOTE: You need svn version 1.5 or better for this technique. MacOS X Snow Leopard includes a 1.6.x version of svn, which is plenty good enough. So does Ubuntu Linux. If you don't have svn 1.5 or better, don't worry about it, just check out the sandbox project the regular way.

This command creates a new svn repository, of course you can use an existing one, such as a beanstalk repository. For more information about svn see the  official svn red bean book. Of course you should substitute your own preferred location for /Users/boutell here:

svnadmin create /Users/boutell/myrepo

IMPORTANT: if you are making your own repository make sure you turn off enable-rep-sharing to avoid this error:

svn: no such table: rep_cache

To prevent this, after you create your repository (see above), edit /Users/boutell/myrepo/db/fsfs.conf and add this line:

enable-rep-sharing = false

This disables an optional optimization that can cause problems. Unfortunately it is turned on by default in svn on MacOS X Snow Leopard. Thanks to Pablo Godel of ServerGrove for pointing out the issue.

Now, this command copies the project from our repository to yours:

svnforeigncopy http://svn.apostrophenow.org/sandboxes/asandbox/branches/1.5 file:////Users/boutell/myrepo/demosite Sites/demosite

Those arguments are the path you're copying from, the path you're copying to, and the local checkout folder where you'll work with the end result (also used as a scratchpad during the copy operation).

You'll be prompted to commit to svn a couple of times (you may need to set your VISUAL environment variable if you have never done so before), and the checkout of symfony in lib/vendor means it'll take a little while to do the final 'update' that brings down the related plugins and Symfony itself. When it's over, though, you have our project cloned in your own repository where you can commit your own changes without losing the connection to the stable branch of our plugin.

Apache Configuration

Once you have fetched the code by your means of choice, you're ready to configure your testing web server to recognize a new website. Light up the folder asandbox/web as a website named asandbox or whatever suits your needs via MAMP, httpd.conf or whatever your web hosting environment requires. As with any Symfony project you'll want to allow full Apache overrides in this folder. See config/vhost.sample for tips on virtual host configuration for Apache. Make sure the directives in web/.htaccess will be honored by your server.

(Confused about this MAMP stuff? Wondering how you can test websites on your own computer? You really should pick up  MAMP if you are on a Mac. Windows and Linux users should consider using  XAMPP. These are all-in-one packages with PHP, MySQL, Apache and everything else you need to test real websites on your own computer. You can also install Apostrophe directly on a web hosting account. We just think you'll find web development with Apostrophe and in general oh so much more pleasant if you learn to test on your own computer before uploading things.)

PHP Configuration

There is a php.ini setting that determines whether parameters in URLs are separated by & or by &. Apostrophe currently requires that they be separated by &.

In most web hosting setups, you can add this line to web/.htaccess of your Apostrophe project to ensure that the separator is &:

php_value arg_separator.output &

If PHP directives are not honored in .htaccess files in your hosting setup, you can do this in your php.ini file:

arg_separator.output = "&"

You must also have a reasonable PHP memory_limit setting. We recommend 64 megabytes of memory for PHP:

memory_limit = 64M

A few Linux distributions set unrealistic memory limits on PHP by default. In this case you may get a blank page when accessing Apostrophe sites.

Don't forget to restart Apache if you make changes in php.ini.

Note that without this rule content editing will not work properly in Apostrophe.

Symfony Configuration

Yes, this is a preconfigured sandbox project, but you do have to adjust a few things to reflect reality on your own computer.

Now create the config/databases.yml file, which must contain database settings appropriate to your system. Copy the file config/databases.yml.sample as a starting point:

    cp config/databases.yml.sample config/databases.yml

PLEASE DO NOT USE AN EXISTING DATABASE. Make a new MySQL database just for your new Apostrophe site. The following steps will make the database for you if permissions allow. Any unrelated data will be removed from an existing database. It's never a good idea to share a database between unrelated pieces of software.

If you are testing with MAMP the default settings (username root, password root, database name asandbox) may work just fine for you. If you are testing on a staging server you will need to change these credentials.

Also create your properties.ini file:

    cp config/properties.ini.sample config/properties.ini

In Symfony properties.ini contains information about hosts that a project can be synced to, in addition to the name of the project. The sample properties.ini file just defines the name of the project. You'll add information there when and if you choose to sync the project to a production server via project:deploy or our enhanced version, apostrophe:deploy. See the Symfony documentation for more information about that technique.

At this point you're ready to use the checkout of Symfony's 1.4.x stable branch that is included in the project. If you want to use a different installation of Symfony, such as a shared install for many sites (note that only 1.3.x and 1.4.x are compatible, or indeed supported as of this date), copy config/require-core.php.example to config/require-core.php and edit the paths in that file.

Next, cd to the asandbox folder and run these commands.

(Windows users: you should remove the web/apostrophePlugin, web/apostropheBlogPlugin, etc. folders first. These are the subfolders in web that end in Plugin. Unix/Linux? users don't have to worry about this.)

    ./symfony plugin:publish-assets
    ./symfony doctrine:build --all
    ./symfony doctrine:data-load

This will create a sample database from the fixtures files.

If you prefer, you can pull down our full demo site as an alternative to the somewhat bland fixtures site. Replace the doctrine:data-load command with this one (it's OK to do this if you already did the other command):

    ./symfony apostrophe:demo-fixtures

Note that this task will run for quite a while as media files are included in the download.

Now set the permissions of data folders so that they are writable by the web server. Note that svn does NOT store permissions so you can NOT assume they are already correct:

    ./symfony project:permissions

Our apostrophePlugin extends project:permissions for you to include the data/writable folder in addition to the standard web/uploads, cache and log folders. Handy, isn't it?

If you prefer you can do this manually:

    chmod -R 777 data/a_writable
    chmod -R 777 web/uploads
    chmod -R 777 cache
    chmod -R 777 log

More subtle permissions are possible. However be aware that most "shared hosting" environments are inherently insecure for a variety of reasons. Production Symfony sites should run on a virtual machine of their own, or share a VM only with other sites written by you. So before criticizing the "777 approach," be sure to  read this article on shared hosting and Symfony.

Next, build the site's search index for the first time (yes, search is included). After this, you won't need to run this command again unless you are deploying to a new environment such as a staging or production server and don't plan to sync your content with sfSyncContentPlugin:

    ./symfony apostrophe:rebuild-search-index --env=dev

(You can specify staging or prod instead to build the search indexes for environments by those names. You'll want that later when working on a production server.)

You can now log in as admin with the password demo to see how the site behaves when you're logged in (if you used the apostrophe:demo-fixtures task, the password will be demo). Start adding subpages, editing slots, adding slots to the multiple slot content area... have a ball with it!

Note: For all versions of the demo site, the login is `admin` and the password is `demo`.

The Hard Way: Adding apostrophePlugin To An Existing Site

Those who installed the sandbox just now can skip right over this section.

Installing the sandbox is the easy way to install Apostrophe. The notes that follow assume you're doing it the hard way, without starting from the asandbox project. You should use the sandbox unless you have a compelling reason not to.

Begin by installing the following Symfony plugins into your Symfony 1.3/1.4 project:

  • sfJqueryReloadedPlugin
  • sfDoctrineGuardPlugin (5.0.x, preferably the svn trunk)
  • sfDoctrineActAsTaggablePlugin
  • sfWebBrowserPlugin
  • sfFeed2Plugin
  • sfSyncContentPlugin (recommended but not required)
  • And of course,  apostrophePlugin

We strongly encourage you to do so using svn externals.

For sfDoctrineGuardPlugin you must use the 5.0.x series. This version adds first name, last name and email address in the schema and uses the default Doctrine integer type.

If you are using svn externals to fetch plugins, pin your svn:external for sfDoctrineGuardPlugin to the svn trunk branch:


Also, if you are using svn externals you will need to be sure to create the necessary symbolic links from your projects web/ folder to to the web/ folders of the plugins that have one. Use the plugin:publish-assets task, or create your own links with a relative path:

    cd web
    ln -s ../plugins/apostrophePlugin/web apostrophePlugin
    # Similar for other plugins required

The search features of the plugin rely on Zend Search, so you must also install the Zend framework.  The latest version of the minimal Zend framework is sufficient. If you choose to install this system-wide where all PHP code can easily find it with a require statement, great. If you prefer to install it in your Symfony project's lib/vendor folder, you'll need to modify your ProjectConfiguration class to ensure that require statements can easily find files there:

    class ProjectConfiguration extends sfProjectConfiguration
      public function setup()
        // We do this here because we chose to put Zend in lib/vendor/Zend.
        // If it is installed system-wide then this isn't necessary to
        // enable Zend Search
          sfConfig::get('sf_lib_dir') .
            '/vendor' . PATH_SEPARATOR . get_include_path());
        // for compatibility / remove and enable only the plugins you want

Create an application in your project. Then create a module folder named a as a home for your page templates and layouts (and possibly other customizations):

    mkdir -p apps/frontend/modules/a/templates

The CMS provides convenient login and logout links. By default these are mapped to sfGuardAuth's signin and signout actions. If you are using sfShibbolethPlugin to extend sfDoctrineGuardPlugin, you'll want to change these actions in apps/frontend/config/app.yml:

        domain: duke.edu
        actions_logout: "sfShibbolethAuth/logout"
        actions_login: "sfShibbolethAuth/login"

You can also log in by going directly to /login. If you don't want to display the login link (for instance, because your site is edited only you), just shut that feature off:

        login_link: false

You will also need to enable the Apostrophe modules in your application's settings.yml file. Of course you may need other modules as well based on your application's needs:

      - a
      - aSync
      - aNavigation
      - aMedia
      - aMediaBackend
      - aRichTextSlot
      - aTextSlot
      - aRawHTMLSlot
      - aSlideshowSlot
      - aVideoSlot
      - aImageSlot
      - aButtonSlot
      - aPDFSlot
      - aFeedSlot
      - sfGuardAuth
      - aUserAdmin
      - aGroupAdmin
      - aPermissionAdmin
      - sfGuardPermission
      - taggableComplete
      - aNavigation
      - default
      - aAdmin
      - aTagAdmin
      - aCategoryAdmin

Apostrophe edits rich text content via the FCK editor. A recent version of FCK is included with the plugin. However you'll need to enable FCK in your settings.yml file, as follows:

      rich_text_fck_js_dir:   apostrophePlugin/js/fckeditor

Setting Permissions

You must run the project:permissions task to set the permissions of your data folders.

Output Escaping

Recent versions of Apostrophe are designed to work with or without Symfony's output escaping feature enabled.

Loading Fixtures

Now, load the fixtures for a basic site. Every site begins with a home page with all other pages being added as descendants of the home page:

    ./symfony doctrine:build --all
    ./symfony doctrine:data-load

Note: if you are adding apostrophePlugin to an existin site you probably don't want to delete your other tables and start over! You can do:

    ./symfony doctrine:build --all-classes --sql

To build the model classes and to build the SQL code that would be sufficient to recreate your database. Then look in data/sql/schema.sql for the CREATE TABLE statements for tables beginning with the a_ prefix.

Ideally you would use Doctrine's migration schema diff task instead. Unfortunately there is currently a bug in Symfony and Doctrine that prevents successful use of this feature with tables that use inheritance. See  Symfony bug 7272 for more information and patches if you are interested in pursuing that approach. It's probably easier to just locate the CREATE TABLE statements.

You will also want to load the fixtures for the apostrophePlugin or, depending on your needs, edit them to suit your purposes better first. You can do so without clobbering your existing database:

./symfony doctrine:data-load --append plugins/apostrophePlugin/data/fixtures/seed_data.yml

In particular you must have a home page and the hidden /admin and /admin/media engine pages.

Also see the fixtures provided with the sandbox project for strongly recommended (but not mandatory) permissions and groups settings.

.htaccess Rules For Media

The media module of Apostrophe uses carefully designed URLs to allow images to be served as static files after they are generated for the first time. This is done at the Apache level to maximize performance: PHP (and therefore Symfony) don't have to get involved at all after the first time an image is rendered at a particular size.

The following special .htaccess rules are required to enable this. These should be copied to your .htaccess file after the RewriteBase / rule, if you are using one, but before any other rules.

    ###### BEGIN special handling for the media module's cached scaled images
    # If it exists, just deliver it
    RewriteCond %{REQUEST_URI} ^/uploads/media_items/.+$
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule .* - [L]
    # If it doesn't exist, render it via the front end controller
    RewriteCond %{REQUEST_URI} ^/uploads/media_items/.+$
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]
    ###### END special handling for the media module's cached scaled images

Routing Rules

Beginning with version 1.5 there is no default route for CMS pages. That's because it conflicts with plugins like our blog plugin that need to register engine routes that are seen first, and it's almost never what you want anyway.

Our sandbox maps CMS pages to the root of the site, via an a_page route, like this. This should be at the END of your routing.yml:

    # A default rule that gets us to actions outside of the CMS.
      url:   /admin/:module/:action/*

    # A homepage rule is expected by a and various other plugins,
    # so be sure to have one
      url:  /
      param: { module: a, action: show, slug: / }

    # Put any routing rules for other modules and actions HERE,
    # before the catch-all rule that routes URLs to the
    # CMS by default.

    # Must be the last rule

      url:   /:slug
      param: { module: a, action: show }
      requirements: { slug: .* }

Thanks to Stephen Ostrow for his help with these rules.

You can change the a_page rule, prefixing the page slug with anything you wish, but you must have such a rule and it must be named a_page. Otherwise Apostrophe engines, including the built-in media repository functionality and media slots, will not work.

layout.php Requirements

Apostrophe's non-CMS pages, such as the "reorganize" feature, the user admin feature and the media repository, expect a layout that offers certain overridable Symfony slots, in particular the a-subnav slot. The media repository overrides this slot to offer media navigation links instead of a list of subpages. If your application layout does not offer such a slot to override, the media repository will be missing some of its interface.

Take a close look at modules/a/templates/layout.php and check out the way we've provided the ability for page templates to override various parts of the layout via Symfony slots. If you experience missing bits of the UI with your own layout, make sure you offer the same slots at appropriate points.

** Prior to Apostrophe 1.0.7 ** the media repository in particular defaults to using a built-in layout that is not really suitable for its current markup. You can fix this with an app.yml setting which is also found in the sandbox project:

    use_bundled_layout: false

Beginning in Apostrophe 1.0.7 this is no longer necessary.

Styling Requirements

The user interface will be essentially complete at this point, but you may notice a few areas in the media repository where the look and feel is a bit too austere unless you borrow elements from the sandbox project's main.css file or apply some styles of your own. In fact in Apostrophe 1.1 we will be migrating toward moving more of the hard-to-override, site-design-specific CSS from a.css to the main.css file of the sandbox project. So you may want to refer to that file as a reference.

Set Permissions

In Symfony, the cache and web/uploads folders are always world-writable so that the web server can store files. Apostrophe adds one more such folder, data/a_writable. This folder is used for files that should be writable by the web server but not directly accessible via a URL. This folder is used for search indexes and other data that does not live in the database.

You can set up this folder yourself, but it's more convenient to use Symfony's project:permissions task, which apostrophePlugin enhances to handle this folder:

./symfony project:permissions

Performance Optimization

Sites with many pages sometimes require some tuning for good performance.

By default, Apostrophe is configured to provide good navigation and reasonable performance without running out of memory, even if your site has thousands of pages. Previously a separate setting was provided to specify that your site has many pages, but this setting has been removed as we've found the code for the "worst case" scenario is acceptably fast on small sites too.

However, there is an issue with searches on sites with thousands of pages. Searches for common words can exhaust the memory available.

You can address this by setting a hard limit on the number of pages Apostrophe should consider when generating search results. Note that this is not the same thing as the number of results the user will see, because some results may be locked pages the user is not eligible to see. That filtering takes place after the hard limit, otherwise it does not save memory. So the limit should be set generously.

To set a hard limit on the memory required for a search, set this app.yml option:

    search_hard_limit: 1000

1000 is a good choice because it will not exhaust a realistically chosen PHP memory_limit and almost certainly will not exclude any worthwhile results either.

Clear the Cache and Get to Work!

No Symfony developer will be shocked to hear that you need to clear your Symfony cache at this point:

./symfony cc

Scheduled Tasks: Enabling Linked Accounts

Version 1.5 and above: if you wish to take advantage of the "Linked Accounts" feature, which automatically brings new media into the media repository from Youtube and other media services specified by the site administrator, you will need to schedule the following command line task to run on a scheduled basis. We suggest using a cron job to run this task every 20 minutes. Change the --env setting as appropriate to your environment:

./symfony apostrophe:update-linked-accounts --env=prod

For many services you will also need to obtain an api key for your specific site from the service in question. For details try out the "Search Services" feature and click the configuration help links you see there.

Google Analytics

You don't have to use it, but Apostrophe has support for Google Analytics baked in. You can specify your Google Analytics account and, if appropriate, domain name in app.yml:

      account: XX-888888-1
      # Only needed if Google includes it in their sample embed code
      # domainName: .apostrophenow.com

If these options are set Apostrophe's default layout will automatically include Google Analytics tracker code.

Twitter API v1.1

As of March 2013, Twitter is eradicating its v1.0 API and RSS feeds in general. This means that calls to Twitter's API now require OAuth credentials from a registered Twitter App. To prevent this from affecting the apostrophe feed slot, we've baked in a solution that takes Twitter App credentials and returns an old-style RSS feed. You must do this if you plan on using the feed slot to display a twitter feed on your site.

First, register an app with Twitter (free and easy):

- Create a twitter account if you don't already have one

- Go to dev.twitter.com

- Hover over your username in the top right corner and go to "My Applications"

- Click "Create a new application"

- When your app has been created, note the information under "OAuth Settings", which you'll need for the next step.

Second, in app.yml:

      adapter: aTwitterPassthroughAdapter
        timeout: 30
        consumer_key: 'yourconsumerkey'
        consumer_secret: 'yourconsumersecret'
        user_agent: YourAppName

This specifies an adapter for feed slots capable of using your consumer key and secret to call twitter's new API.

If you are using aBetterTwitterSlot, you'll also need to set up a route in your frontend/config/routing.yml file:

  url: /api/twitter
  param: { module: aBetterTwitterSlot, action: twitter }


We're done installing Apostrophe! On to the editor's guide, which briefly explains how to edit content with Apostrophe- briefly because it is so much more fun to simply use it.

Continue to the Editor's Guide

Up to the Overview