Skip to content

Joining a PageTable field results in an empty value when the field has more than one page #2066

Closed
@tuomassalo

Description

@tuomassalo

NB: this is closely related to #1988

Short description of the issue

When a page has a PageTable field and it's joined with e.g. $pages->get($selector, ['loadOptions' => ['joinFields' => ['c_ref']]]) or $pages->find($selector, ['loadOptions' => ['joinFields' => ['c_ref']]]) (as opposed to id=123, field=c_ref), the resulting $p->c_ref is empty when the field contains more than one page.

Expected behavior

Adding joinFields should not affect the result, only performance.

Actual behavior

If there are more than one subpage, they are not fetched.

Screenshots/Links that demonstrate the issue

Possible cause: PageValues.php tries to explode the value, but only does it if the GROUP_CONCAT separator is seen in the results.

Issue #1988 was fixed by making sure that $value is an array.

I believe the correct way to fix this would be to avoid searching for separators in the string, and instead make sure that we always explode after GROUP_CONCAT. But it seems to me that instead we could just change the earlier FieldtypePageTable.php fix like this:

-if($value && !is_array($value)) $value = array($value);
+if($value && !is_array($value)) $value = explode(FieldtypeMulti::multiValueSeparator, $value);

Steps to reproduce the issue

The script below creates a parent and child template, p and c, and a field c_ref in the p template. Then it adds these pages:

Parent: parent-a
  Child: child-a1
  Child: child-a2
Parent: parent-b
  Child: child-b1

If run without GET params, it fetches all the pages and prints the above output. If run with ?join, only the lone child child-b1 is printed.

Setup/Environment

  • ProcessWire version: latest dev
  • (Optional) PHP version: 8.4

The script:

<?php

$processwirePath = '/var/www/html/';
include($processwirePath . 'index.php');
header('Content-Type: text/plain');

////// Install fixture templates, field and pages.
////// First, clean up previous run (if any).

// Remove pages with template 'p' or 'c'.
$pagesToRemove = $pages->find("template=p|c");
foreach ($pagesToRemove as $page) $pages->delete($page, true);

$pagesToRemove = $pages->find("template=p|c");
foreach ($pagesToRemove as $page) $pages->delete($page, true);

// Remove templates 'p' and 'c'.
$pTemplate = $templates->get('p');
if ($pTemplate) $templates->delete($pTemplate);

$cTemplate = $templates->get('c');
if ($cTemplate) $templates->delete($cTemplate);

// Remove field 'c_ref' if it exists.
$field = $fields->get('c_ref');
if ($field) $fields->delete($field);

// Create templates and field.

$pTemplate = $templates->add('p');
$pTemplate->save();

$cTemplate = $templates->add('c');
$cTemplate->save();

$field = $fields->makeItem();
$field->name = 'c_ref';
$field->type = 'PageTable';
$field->label = "c_ref";
$field->template_id = [$cTemplate->id];
$field->inputfield = "InputfieldPageTable";
$field->parent_id = 1;
$field->save();
$pTemplate->fields->add($field);
$pTemplate->save();

// Create pages.
$parent_a = $pages->add('p', '/', 'parent-a');

$child_a1 = $pages->add('c', '/', 'child-a1');
$parent_a->c_ref->add($child_a1);
$parent_a->save();

$child_a2 = $pages->add('c', '/', 'child-a2');
$parent_a->c_ref->add($child_a2);
$parent_a->save();

$parent_b = $pages->add('p', '/', 'parent-b');

$child_b1 = $pages->add('c', '/', 'child-b1');
$parent_b->c_ref->add($child_b1);
$parent_b->save();

//////// Now everything is set up.

$options = isset($_GET['join']) ? ['loadOptions' => ['joinFields' => ['c_ref']]] : [];

echo "--- get() ---\n";

foreach (['parent-a', 'parent-b'] as $parentName) {
    $parent = $wire->pages->get("name=$parentName", $options);
    echo "Parent: $parentName\n";

    foreach ($parent->c_ref as $child) {
        echo "  Child: " . $child->name . "\n";
    }
}

$wire->pages->unCacheAll();

echo "--- find() ---\n";

foreach ($wire->pages->find("template=p", $options) as $parent) {
    echo "Parent: $parent->name\n";

    foreach ($parent->c_ref as $child) {
        echo "  Child: " . $child->name . "\n";
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions