Perch “standard” to Perch Runway migration—the missing steps

Post #10, veröffentlicht am in
  • How to
  • Web design

I have recently migrated a bunch of websites, that were on Perch version 3.2 (a.k.a. the last “regular” release), to Perch Runway 4.x. It is not always an easy route, is what I have learnt.

Runway has been around for quite some time and was sort of the bigger sibling of standard Perch—some called the latter “Perch proper“.
After the CMS changing owners in early 2021, the standard version has been retired.

There is a helpful guide in the docs for migrating. That article lacks some minor details, though, that I’ll jot down here for future reference.

MySQL errors

Many times, when migrating, I got a massive list of Syntax error or access violations after replacing the core folder and reloading the admin panel in the browser.

A browser screenshot showing rows and rows of MySQL errors.

As per this old forum post, these can be ignored.
At the bottom of the page displaying the errors you can “accept these errors and continue.” I haven’t had any issues following that so far.


Although it being mentioned in the migration guide, the URL to an explanation of the rewrite rules required for Runway is broken. Here’s the correct document: docs.grabaperch.com/runway/getting-started/installing/rewrites
Basically, replace whatever rewrites you had in your .htaccess so far with this:

# Perch Runway
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/perch
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /perch/core/runway/start.php [L]    

Include the runtime conditionally and relative to the site root

In the beginning of my migration journey I often came across errors notifying me, that I included the runtime.php more than once. When removing it from the page template affected, I would end up it being missing entirely in certain constellations. To avoid that, include the runtime like this:

if (!defined('PERCH_RUNWAY')) include($_SERVER['DOCUMENT_ROOT'] . '/perch/runtime.php');

Missing “error master pages”

If it is not there already, copy the directory /perch/templates/pages/errors/ from the 4.x folder you downloaded from the Perch website into the corresponding folder of your installation.
Coming from standard Perch, you likely rolled your own 404 page and redirected to that in your .htaccess.
In Runway you simply use the page template given in the errors folder. Rewriting is handled automatically. Alter the template to your liking, of course.

Amend page templates to account for missing physical files

If you decide to make “your Perch site more Runway-like”, remember to also update the page option to the perch_content_custom calls in your PHP templates. Given, you are retrieving content from another page than the one using the template, that is.
Instead of

perch_content_custom('Content', [
    'page' => '/news.php'

set the option to:

perch_content_custom('Content', [
    'page' => '/news'

Otherwise you will get “Template not found” notices instead of the content you were looking for.

Issues with localized dates

Most websites I do are in German. Thus, the localization of dates is unavoidable in some instances, i.e. if we want to display a month’s name, rather than its one- or two-digit representation.
After upgrading to Perch Runway 4.x, all the sites trying that showed broken dates—e.g. “%041 %2023” instead of “März 2023”.
I suspected this being related to the deprecation of strftime in PHP 8.1 (and it well might be), but the problem persisted after reverting to PHP 7.4. The Perch support team wasn’t able to help me with this and they were not able to reproduce the issue. So I wrote a template filter, that replaces the standard English-based names for weekdays and months with their German counterparts.
This is cumbersome, somewhat hacky, and the translations live inside the filter for now. Also it is not suited for multi-lingual setups. But it reinstated the correct format of the dates.
Here’s the filter:

class PerchTemplateFilter_localdatestrings extends PerchTemplateFilter 
    public function filterAfterProcessing($value, $valueIsMarkup = false)
        $strings = [
            'January'   => 'Januar',
            'February'  => 'Februar',
            'March'     => 'März',
            'April'     => 'April',
            'May'       => 'Mai',
            'June'      => 'Juni',
            'July'      => 'Juli',
            'August'    => 'August',
            'September' => 'September',
            'October'   => 'Oktober',
            'November'  => 'November',
            'December'  => 'Dezember',
            'Monday'  => 'Montag',
            'Tuesday'  => 'Dienstag',
            'Wednesday'  => 'Mittwoch',
            'Thursday'  => 'Donnerstag',
            'Friday'  => 'Freitag',
            'Satday'  => 'Samstag',
            'Sunday'  => 'Sonntag',
            'Mon'  => 'Mo',
            'Tue'  => 'Di',
            'Wed'  => 'Mi',
            'Thu'  => 'Do',
            'Fri'  => 'Fr',
            'Sat'  => 'Sa',
            'Sun'  => 'So',
        return $strings[$value];
PerchSystem::register_template_filter('localdatestrings', 'PerchTemplateFilter_localdatestrings');

After incorporating that into your filters setup, use it like this in your Perch template:

<perch:content id="date" type="date" format="F" filter="localdatestrings"> <perch:content id="date" type="date" format="Y">

The filter could be enhanced to do more complex convertions. But it serves its purpose for now.
Feel free to grab it and alter it to your requirements.


Don’t forget to redo your sitemap, too. It should no longer be a PHP file sitting in your folder structure, but a virtual page, just like all the other ones. Treat its template like those of the remaining pages, add the route sitemap.xml in the page’s details and you’re good to go.

Anything else? Anyone?

Have you found a missing piece you’d like to see added here?
Send me an email or hit me up on Mastodon!