Forum

Thread tagged as: Question, Discussion, Runway

Leveraging Runway: Best Practices for Efficiency and Useability

Hi! I'm using Runway to develop a website for a commercial real estate client. My site structure looks like this:

Home
> Locality A
>> Property 1 (call Agent Smith)
>> Property 2 (call Agent Jones)
> Locality B
>> Property 3 (call Agent Jones)
>> Property 4 (call Agent Williams)

Desired Locality URL: domain.com/locality-a/
Desired Property URL: domain.com/locality-a/property-1/

It's clear to me that my Agents need to be Collections, because they do not need "pages" and are not tied to particular Properties or even Localities.

What's less clear to me is how to structure my Localities and Properties. These do need to render as individual pages, but my initial thought was that if I made Collections of both, that would make it easy to associate Properties with Localities and, in particular, associate new Properties with a Locality (in the same way that Authors are associated with Articles in the Collections demos).

I've gotten so far as a Home page with a working list of links to an admin-created "Locality" page that dynamically populates with a given Locality Collection item. Now I realize I'm going to have to wrestle with perch_page_attributes_extend to get the <head> elements in that page to be properly dynamic as well.

But I'm starting to wonder if I am overcomplicating things for myself and, more importantly, the client. I'm worried they will be be confused by the existance of just one Locality page and one Property page, particularly when it comes time to add a new Property. Perhaps it would be cleaner and easier for them to grok to just deal with pages within Perch admin?

But if I go the Perch-admin-pages route, how do I make it easy for content editors to link Properties with Localities? What mechanism do I use to have, say, a select box in a Perch-admin-based Properties page that functions the same way as the "Authors" field in the various Runway Collections demos? Or is there an easier way to do that?

Thanks for your comments in advance!

Joel Davies

Joel Davies 0 points

  • 4 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

I think you're on the right track. I would have 3 collections:

  1. Properties
  2. Localities
  3. Agents

Think of Properties as the primary data object - the others just serve it. Create a relationship to Localities and Agents, as every property has a location and an agent.

When it comes to adding a new property, the user should only need to go to the Properties collection most of the time. They'll be prompted for the rest.

You might like to abstract your mental models by thinking of collections as venn circles in a Venn diagram. Overlaps are the related content. Categories operate as sorting filters of the collection views.

Duncan Revell

Duncan Revell 78 points
Registered Developer

If it helps, you could also add a collection to a page (in a virtual sense) - when an admin edits the page, they are presented with a region that is basically a link through to edit a collection. So in your example, the admin clicks on the property page and has a "region" called Property List (for example) that is just a link to edit the property collection items. At least then it appears as if the one page has a list of all the properties in it.

To (potentially) further complicate matters, you could get away with having just one page for your localities/properties (and even agents). Maybe just call it "Site Data" (for example) and have all three collections linked to it. When the admin edits the page, they will be presented with three lists of data - localities, properties and agents. You could associate your routes to that one page and the page itself would contain all your php that conditionally calls content based on the route.

Runway is so flexible, you can abstract it to a way that best suits your client - although I would steer away from having lots of admin pages!

Thanks for your insightful responses. As developers, we're always looking for ways to be more efficient and "dry", which is why I was intrigued by Collections in the first place.

Users, however, want things as simple as possible in my experience.

So are y'all finding that users aren't necessarily thrown off by the abstraction of Collections vs the concreteness of admin Pages?

My concern here is most of the content editing they will be doing will be photo/copy tweaking. The actual addition of a new Property might be as infrequent as once or twice a year.

Drew McLellan

Drew McLellan 2638 points
Perch Support

I think it'll be just fine.

So are y'all finding that users aren't necessarily thrown off by the abstraction of Collections vs the concreteness of admin Pages?

My concern here is most of the content editing they will be doing will be photo/copy tweaking. The actual addition of a new Property might be as infrequent as once or twice a year.

From my experience its the selling point of Runway. You always have to measure your client's need for in-depth explanations. Since you might be arguing for a UI experience that is closely tied to business logic ... i'm not sure how its not possible to be modelling knowledge assets and process in the delivery of a new web service.

Okay, folks, I'm taking your advice and sticking with Collections.

However, I'm still stymied at getting meta information into the detail page for my first Collections level: Localities

My Perch admin localities page uses this file locality.php:

<?php if (!defined('PERCH_RUNWAY')) include($_SERVER['DOCUMENT_ROOT'].'/perch/runtime.php'); ?>
<?php perch_layout('global/header', ['body-class' => 'locality',]); ?>
<?php
  perch_collection('Localities', [
    'template'   => 'localities.html',
    'filter' => 'locality_slug',
    'match' => 'eq',
    'value' => perch_get('s'),
    'count' => 1,
  ]);
?>
<?php perch_content_custom('Contact Form', []);
?>
<?php perch_layout('global/footer');

This works; with the right URL I get the data displayed for the given Collection item. However, while I have fields defined in my localities.html template for meta data like description and keywords, I can't figure out how to get that data into my page's meta tags.

I'm aware that to do this I probably have to use perch_page_attributes_extend somewhere. Where to put that array and how to move variables from there into my <head> tags is where I am stuck. Does that go in my template > pages > locality.php file? In my layouts > global > header.php file? Should I create a variant layouts > global > header-localities.php file instead?

Part of my confusion is when the docs talk about creating virtual page attributes, they talk about it in the context of the Blogs app, which I'm not using here.

Here's my "default" header.php layout:

<?php
  $domain        = 'https://'.$_SERVER["HTTP_HOST"];
  $url           = $domain.$_SERVER["REQUEST_URI"];
  $sitename      = "My Mighty Site";
  $title = perch_pages_title(true);
  PerchSystem::set_var('mighty_sitename',$sitename);
  PerchSystem::set_var('mighty_domain',$domain);
  PerchSystem::set_var('mighty_url',$url);
  PerchSystem::set_var('mighty_title',$title);
  perch_content_create('Contact Form', array(
      'template'=>'contact-form.html'
  ));
?>
<!doctype html>
<html class="no-js" lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php perch_pages_title(); ?></title>
    <?php $sharing_image = '/sherp/resources/og-images/big-picture.jpg'; ?><?php perch_page_attributes(); ?>
    <link rel="icon" href="https://www.mymightysite.com/favicon.ico?v=2">
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,700' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="/assets/css/app.css">
  </head>

<?php 
    if (perch_layout_has('body-class')) {
        echo '<body class="'.perch_layout_var('body-class', true).'">';
    }else{
        echo '<body>';
    }
?>

Any suggestions would be appreciated!

Drew McLellan

Drew McLellan 2638 points
Perch Support

Yes, so the format of perch_page_attributes_extend() would be something like:

perch_page_attributes_extend([
     'description' => 'My custom description',
]);

so it should be a case of grabbing that from your collection to use. Flip the order so that you query the collection first, then you have the data to use before you call your layout:

<?php 

    $localities = perch_collection('Localities', [ 
        'template' => 'localities.html', 
        'filter' => 'locality_slug', 
        'match' => 'eq', 
        'value' => perch_get('s'), 
        'count' => 1, 
        'skip-template' => true,
        'return-html' => true,
    ]);

    if (isset($localities[0])) {
        perch_page_attributes_extend([
            'description' => $localities[0]['id_of_desc_field'],
            ]);
    }

    perch_layout('global/header', ['body-class' => 'locality',]);  

    echo $localities['html'];

    perch_content_custom('Contact Form', []); 

    perch_layout('global/footer');

Thanks, Drew, that worked great. The last niggling bit was passing in my Collection template's locality_name field into the <title>. I hacked around with that for a while.

Here's my templates > pages > locality.php, in which I used a layout variable to pass the locality_name into a revised version of my global/header layout :

<?php if (!defined('PERCH_RUNWAY')) include($_SERVER['DOCUMENT_ROOT'].'/perch/runtime.php'); ?>
<?php 
  $localities = perch_collection('Localities', [ 
    'template' => 'localities.html', 
    'filter' => 'locality_slug',
    'match' => 'eq', 
    'value' => perch_get('s'),
    'count' => 1,
    'skip-template' => true,
    'return-html' => true,
  ]);
  if (isset($localities[0])) {
    perch_page_attributes_extend([
      'description' => $localities[0]['locality_meta_description'],
      'keywords' => $localities[0]['locality_meta_keywords'],
      'og_image' => $localities[0]['locality_thumbnail'],
      ]);
  }
  perch_layout('global/header-locality', [
    'body-class' => 'locality',
    'loc_title' => $localities[0]['locality_name'],
  ]);
  echo $localities['html'];
  perch_content_custom('Contact Form', []);
  perch_layout('global/footer');

The new templates > layouts > global > header-locality.php plugs in the passed perch_layout_var():

<?php
  $domain        = 'https://'.$_SERVER["HTTP_HOST"];
  $url           = $domain.$_SERVER["REQUEST_URI"];
  $sitename      = "My Mighty Site";
  perch_content_create('Contact Form', array(
      'template'=>'contact-form.html'
  ));
?>
<!doctype html>
<html class="no-js" lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php perch_layout_var('loc_title'); ?> Shopping Centers</title>
...

It confused me at first that I couldn't declare the new page title in the perch_page_attributes_extend() array, but to do that I would have to have a <perch:pages> tag for it in my templates > pages > attributes default.html, correct? Since I don't, I have to use the layout variable.

Duncan Revell

Duncan Revell 78 points
Registered Developer

You can use pageTitle with perch_page_attributes_extend()

There's no need to declare it in default.html - it's a built-in variable.

Oooh, good one. Thanks for the tip, Duncan!