Jump to content

Connect Page Fields


Robin S

Recommended Posts

ConnectPageFields

Allows the connecting of two related Page fields so that changing one updates the other.

Purpose of module

An example: suppose your website is about movies. You have a template "movie" with Page field "actors". For each movie you add the actors that appear in the movie. All good, but what if you want to find results like...

  • the 10 actors who have appeared in the most movies
  • actors who haven't appeared in any movies since 1990

You cannot retrieve these pages with a single efficient $pages->find() query, and must load a large PageArray into memory in order to iterate or filter it. For the sake of making these types of queries more efficient you could structure your templates/fields so that movies are added to actors instead, but this may be a less comfortable workflow and can run into equivalent problems (e.g. "find the 10 movies with the largest cast").

The solution is to have a two-way relationship so that movie pages have an "actors" Page field and actor pages have a "movies" Page field. This module will keep these two Page fields in sync so that adding "Ryan Gosling" to "Drive" automatically adds "Drive" to "Ryan Gosling".

Also, you can select the same Page field in both Page field A and Page field B. For example, create a "Related" Page field for related pages. Choose "Related" for both fields in a pair in the module config. Now when you add "Orange buffoon" to Related for "Donald Trump", "Donald Trump" is automatically added to Related for "Orange buffoon".

Usage

Install the ConnectPageFields module. If you haven't already done so, create the two Page fields you want to connect and add them to templates.

In the module config select the two Page fields in a "Connected field pair" row as Page field A and Page field B.

You can add rows as needed using the "Add another row" button.

Troubleshooting

Make sure you have set the "Selectable Pages" settings for each Page field correctly:

  • The settings for Page field A should allow pages using the template(s) that Page field B has been added to.
  • The settings for Page field B should allow pages using the template(s) that Page field A has been added to.

 

http://modules.processwire.com/modules/connect-page-fields/
https://github.com/Toutouwai/ConnectPageFields

 

Module config:

connect-config.png

 

Demo showing how changing one Page field updates the other:

connect-page-fields-2.gif

  • Like 39
  • Thanks 1
Link to comment
Share on other sites

7 hours ago, fbg13 said:

Might be worth mentioning that it works with the same field too.

Sounds interesting. Can you give an example of how that could be useful?

Maybe something like a Friends field? On page "Bob", "Sue" is added to Friends - so on page "Sue", "Bob" is automatically added to Friends. Just trying to think through the different use cases for the module.

Link to comment
Share on other sites

23 minutes ago, Robin S said:

Can you give an example of how that could be useful?

For pages related to same kind of pages: movies (Ironman related to Ironman 2, Avengers etc), books, games, tutorials, recipes...

If i write IronMan with space between the words i get V@g1n@ Monologues wtf :huh:

  • Like 2
Link to comment
Share on other sites

18 minutes ago, fbg13 said:

For pages related to same kind of pages: movies (Vagina Monologues related to Ironman 2, Avengers etc), books, games, tutorials, recipes...

Got it, thanks. And your interpretation of those movies clearly goes much deeper than mine :D

  • Like 3
  • Haha 1
Link to comment
Share on other sites

On 09/11/2016 at 0:04 AM, fbg13 said:

Well for some reason IronMan with space between the words gives me that no idea why.

Might have caught a virus.

Cough. We used to get a lot of spam with certain movie names on the forum. That's a feature.. kind of :)

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

With AdminOnSteroids the delete checkbox position absolute is overwritten.Untitled.png

Can you make the css selector more specific or use !important?

.Inputfields .InputfieldFieldset li[class*="Inputfield_delete_"] {
	position: absolute!important;
}

 

Link to comment
Share on other sites

On 8.11.2016 at 11:30 PM, Robin S said:

Got it, thanks. And your interpretation of those movies clearly goes much deeper than mine :D

Sorry guys, I have been laughing five minutes alone here for your vagina monologues vs avengers debate :D 

It was indeed our link spam protection plan (that actually worked pretty well). So @fbg13 no worries about any virus, just poor humor from moderators. 

  • Like 3
Link to comment
Share on other sites

  • 4 months later...

Hi @Robin S, I'd like to know if this modules works with API calls, or just within the admin page? Assuming I have a properly setup pages called cards and members that reference each other, and I write something like:

 

$member = $pages->get(123);
$card = $pages->get(456);
$card->members->add($member);
$card->save();

echo $member->card->title;

 

Should I expect the code to output the card's title? I actually tried it out and it didn't work. But maybe I'm just doing something wrong. The fields work okay when setting them using the page editor. Thanks. :)

 

 

Link to comment
Share on other sites

On 24/04/2017 at 7:07 PM, Alxndre' said:

I actually tried it out and it didn't work. But maybe I'm just doing something wrong. The fields work okay when setting them using the page editor.

Hi @Alxndre', I've been away for a bit so just following up now. Yes, the module works with both API and admin changes. In your code example you need to set the output formatting of $card to false before attempting to set values to a field.

Link to comment
Share on other sites

  • 3 months later...

How can I trigger the module for all pages (with paired fields) at once? Like mass-updating all pages? Setting field to itself doesn't work

foreach($pages->find('template=post') as $p) {
    $p->of(false);
    $p->tags = $p->tags;
    echo $p->save();
}

// doesnt work

because the module skips the page if none of the paired field is changed

public function updatePageFields(HookEvent $event) {

    // ...

    foreach($flds as $fld) {

        $this_fname = $fld->name;

        // only if the page is not still null and the field has changed
        if(!$page->id || !$page->isChanged($this_fname)) continue;

		// ...
        }
    }
}

 

 

tags.png

Link to comment
Share on other sites

  • 4 weeks later...
On 8/20/2017 at 12:07 PM, abdus said:

How can I trigger the module for all pages (with paired fields) at once? Like mass-updating all pages?

Sorry for the late reply; I have been on holiday for a while. :)

This module acts only on changes to a Page Reference field - this is deliberate for reasons of efficiency.

If you already have some Page Reference values in place before you start using the module on those fields then you can get things set up with a one-off API operation:

// Get all pages where page_field_a is not empty
$pgs = $pages->find("page_field_a.count>0");
// Get derefAsPage property of page_field_b to distinguish multiple/single page fields
$deref = $fields->get('page_field_b')->derefAsPage;
foreach($pgs as $p) {
    // For this page, get the pages selected in page_field_a
    $selected_pages = $p->page_field_a;
    // Standardise $selected_pages to PageArray in case of "single" field
    if($selected_pages instanceof Page) $selected_pages = $selected_pages->and();
    foreach($selected_pages as $selected_page) {
        // Add this page to page_field_b on the selected page
        $selected_page->of(false);
        if($deref) {
            $selected_page->page_field_b = $p;
        } else {
            $selected_page->page_field_b->add($p);
        }
        $selected_page->save();
    }
}

You can do a similar operation for page_field_b -> page_field_a if needed.

Once you set up the Page Reference field pair in the module config then the module will take care of all changes from that point onwards.

Edited by Robin S
Set page_field_b value differently according to derefAsPage property
  • Like 3
Link to comment
Share on other sites

  • 7 months later...

When I try to save the page that includes one of the pair fields I'm getting the following error:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in C:\xampp\htdocs\mysite\wire\core\Wire.php on line 1118

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in Unknown on line 0

 

Then I've updated my memory_limit to 512M and once again I'm getting this error:

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 262144 bytes) in C:\xampp\htdocs\mysite\wire\core\Wire.php on line 1118

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 262144 bytes) in Unknown on line 0

Link to comment
Share on other sites

@PWaddict, I agree with @kongondo.

If page A has a single page reference field with page B selected in it then page B must not have a single page reference field with page A selected in it. This only applies to two single page reference fields - if one or both are multiple page reference fields then there is no problem. This isn't an issue with this module specifically, just a limitation of PW.

Related GitHub issues:
https://github.com/processwire/processwire-issues/issues/152
https://github.com/processwire/processwire-issues/issues/572

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...